aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-sra.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-01-14 16:56:44 +0100
committerMartin Liska <mliska@suse.cz>2022-01-17 22:12:04 +0100
commit5c69acb32329d49e58c26fa41ae74229a52b9106 (patch)
treeddb05f9d73afb6f998457d2ac4b720e3b3b60483 /gcc/tree-sra.c
parent490e23032baaece71f2ec09fa1805064b150fbc2 (diff)
downloadgcc-5c69acb32329d49e58c26fa41ae74229a52b9106.zip
gcc-5c69acb32329d49e58c26fa41ae74229a52b9106.tar.gz
gcc-5c69acb32329d49e58c26fa41ae74229a52b9106.tar.bz2
Rename .c files to .cc files.
gcc/ada/ChangeLog: * adadecode.c: Moved to... * adadecode.cc: ...here. * affinity.c: Moved to... * affinity.cc: ...here. * argv-lynxos178-raven-cert.c: Moved to... * argv-lynxos178-raven-cert.cc: ...here. * argv.c: Moved to... * argv.cc: ...here. * aux-io.c: Moved to... * aux-io.cc: ...here. * cio.c: Moved to... * cio.cc: ...here. * cstreams.c: Moved to... * cstreams.cc: ...here. * env.c: Moved to... * env.cc: ...here. * exit.c: Moved to... * exit.cc: ...here. * expect.c: Moved to... * expect.cc: ...here. * final.c: Moved to... * final.cc: ...here. * gcc-interface/cuintp.c: Moved to... * gcc-interface/cuintp.cc: ...here. * gcc-interface/decl.c: Moved to... * gcc-interface/decl.cc: ...here. * gcc-interface/misc.c: Moved to... * gcc-interface/misc.cc: ...here. * gcc-interface/targtyps.c: Moved to... * gcc-interface/targtyps.cc: ...here. * gcc-interface/trans.c: Moved to... * gcc-interface/trans.cc: ...here. * gcc-interface/utils.c: Moved to... * gcc-interface/utils.cc: ...here. * gcc-interface/utils2.c: Moved to... * gcc-interface/utils2.cc: ...here. * init.c: Moved to... * init.cc: ...here. * initialize.c: Moved to... * initialize.cc: ...here. * libgnarl/thread.c: Moved to... * libgnarl/thread.cc: ...here. * link.c: Moved to... * link.cc: ...here. * locales.c: Moved to... * locales.cc: ...here. * mkdir.c: Moved to... * mkdir.cc: ...here. * raise.c: Moved to... * raise.cc: ...here. * rtfinal.c: Moved to... * rtfinal.cc: ...here. * rtinit.c: Moved to... * rtinit.cc: ...here. * seh_init.c: Moved to... * seh_init.cc: ...here. * sigtramp-armdroid.c: Moved to... * sigtramp-armdroid.cc: ...here. * sigtramp-ios.c: Moved to... * sigtramp-ios.cc: ...here. * sigtramp-qnx.c: Moved to... * sigtramp-qnx.cc: ...here. * sigtramp-vxworks.c: Moved to... * sigtramp-vxworks.cc: ...here. * socket.c: Moved to... * socket.cc: ...here. * tracebak.c: Moved to... * tracebak.cc: ...here. * version.c: Moved to... * version.cc: ...here. * vx_stack_info.c: Moved to... * vx_stack_info.cc: ...here. gcc/ChangeLog: * adjust-alignment.c: Moved to... * adjust-alignment.cc: ...here. * alias.c: Moved to... * alias.cc: ...here. * alloc-pool.c: Moved to... * alloc-pool.cc: ...here. * asan.c: Moved to... * asan.cc: ...here. * attribs.c: Moved to... * attribs.cc: ...here. * auto-inc-dec.c: Moved to... * auto-inc-dec.cc: ...here. * auto-profile.c: Moved to... * auto-profile.cc: ...here. * bb-reorder.c: Moved to... * bb-reorder.cc: ...here. * bitmap.c: Moved to... * bitmap.cc: ...here. * btfout.c: Moved to... * btfout.cc: ...here. * builtins.c: Moved to... * builtins.cc: ...here. * caller-save.c: Moved to... * caller-save.cc: ...here. * calls.c: Moved to... * calls.cc: ...here. * ccmp.c: Moved to... * ccmp.cc: ...here. * cfg.c: Moved to... * cfg.cc: ...here. * cfganal.c: Moved to... * cfganal.cc: ...here. * cfgbuild.c: Moved to... * cfgbuild.cc: ...here. * cfgcleanup.c: Moved to... * cfgcleanup.cc: ...here. * cfgexpand.c: Moved to... * cfgexpand.cc: ...here. * cfghooks.c: Moved to... * cfghooks.cc: ...here. * cfgloop.c: Moved to... * cfgloop.cc: ...here. * cfgloopanal.c: Moved to... * cfgloopanal.cc: ...here. * cfgloopmanip.c: Moved to... * cfgloopmanip.cc: ...here. * cfgrtl.c: Moved to... * cfgrtl.cc: ...here. * cgraph.c: Moved to... * cgraph.cc: ...here. * cgraphbuild.c: Moved to... * cgraphbuild.cc: ...here. * cgraphclones.c: Moved to... * cgraphclones.cc: ...here. * cgraphunit.c: Moved to... * cgraphunit.cc: ...here. * collect-utils.c: Moved to... * collect-utils.cc: ...here. * collect2-aix.c: Moved to... * collect2-aix.cc: ...here. * collect2.c: Moved to... * collect2.cc: ...here. * combine-stack-adj.c: Moved to... * combine-stack-adj.cc: ...here. * combine.c: Moved to... * combine.cc: ...here. * common/common-targhooks.c: Moved to... * common/common-targhooks.cc: ...here. * common/config/aarch64/aarch64-common.c: Moved to... * common/config/aarch64/aarch64-common.cc: ...here. * common/config/alpha/alpha-common.c: Moved to... * common/config/alpha/alpha-common.cc: ...here. * common/config/arc/arc-common.c: Moved to... * common/config/arc/arc-common.cc: ...here. * common/config/arm/arm-common.c: Moved to... * common/config/arm/arm-common.cc: ...here. * common/config/avr/avr-common.c: Moved to... * common/config/avr/avr-common.cc: ...here. * common/config/bfin/bfin-common.c: Moved to... * common/config/bfin/bfin-common.cc: ...here. * common/config/bpf/bpf-common.c: Moved to... * common/config/bpf/bpf-common.cc: ...here. * common/config/c6x/c6x-common.c: Moved to... * common/config/c6x/c6x-common.cc: ...here. * common/config/cr16/cr16-common.c: Moved to... * common/config/cr16/cr16-common.cc: ...here. * common/config/cris/cris-common.c: Moved to... * common/config/cris/cris-common.cc: ...here. * common/config/csky/csky-common.c: Moved to... * common/config/csky/csky-common.cc: ...here. * common/config/default-common.c: Moved to... * common/config/default-common.cc: ...here. * common/config/epiphany/epiphany-common.c: Moved to... * common/config/epiphany/epiphany-common.cc: ...here. * common/config/fr30/fr30-common.c: Moved to... * common/config/fr30/fr30-common.cc: ...here. * common/config/frv/frv-common.c: Moved to... * common/config/frv/frv-common.cc: ...here. * common/config/gcn/gcn-common.c: Moved to... * common/config/gcn/gcn-common.cc: ...here. * common/config/h8300/h8300-common.c: Moved to... * common/config/h8300/h8300-common.cc: ...here. * common/config/i386/i386-common.c: Moved to... * common/config/i386/i386-common.cc: ...here. * common/config/ia64/ia64-common.c: Moved to... * common/config/ia64/ia64-common.cc: ...here. * common/config/iq2000/iq2000-common.c: Moved to... * common/config/iq2000/iq2000-common.cc: ...here. * common/config/lm32/lm32-common.c: Moved to... * common/config/lm32/lm32-common.cc: ...here. * common/config/m32r/m32r-common.c: Moved to... * common/config/m32r/m32r-common.cc: ...here. * common/config/m68k/m68k-common.c: Moved to... * common/config/m68k/m68k-common.cc: ...here. * common/config/mcore/mcore-common.c: Moved to... * common/config/mcore/mcore-common.cc: ...here. * common/config/microblaze/microblaze-common.c: Moved to... * common/config/microblaze/microblaze-common.cc: ...here. * common/config/mips/mips-common.c: Moved to... * common/config/mips/mips-common.cc: ...here. * common/config/mmix/mmix-common.c: Moved to... * common/config/mmix/mmix-common.cc: ...here. * common/config/mn10300/mn10300-common.c: Moved to... * common/config/mn10300/mn10300-common.cc: ...here. * common/config/msp430/msp430-common.c: Moved to... * common/config/msp430/msp430-common.cc: ...here. * common/config/nds32/nds32-common.c: Moved to... * common/config/nds32/nds32-common.cc: ...here. * common/config/nios2/nios2-common.c: Moved to... * common/config/nios2/nios2-common.cc: ...here. * common/config/nvptx/nvptx-common.c: Moved to... * common/config/nvptx/nvptx-common.cc: ...here. * common/config/or1k/or1k-common.c: Moved to... * common/config/or1k/or1k-common.cc: ...here. * common/config/pa/pa-common.c: Moved to... * common/config/pa/pa-common.cc: ...here. * common/config/pdp11/pdp11-common.c: Moved to... * common/config/pdp11/pdp11-common.cc: ...here. * common/config/pru/pru-common.c: Moved to... * common/config/pru/pru-common.cc: ...here. * common/config/riscv/riscv-common.c: Moved to... * common/config/riscv/riscv-common.cc: ...here. * common/config/rs6000/rs6000-common.c: Moved to... * common/config/rs6000/rs6000-common.cc: ...here. * common/config/rx/rx-common.c: Moved to... * common/config/rx/rx-common.cc: ...here. * common/config/s390/s390-common.c: Moved to... * common/config/s390/s390-common.cc: ...here. * common/config/sh/sh-common.c: Moved to... * common/config/sh/sh-common.cc: ...here. * common/config/sparc/sparc-common.c: Moved to... * common/config/sparc/sparc-common.cc: ...here. * common/config/tilegx/tilegx-common.c: Moved to... * common/config/tilegx/tilegx-common.cc: ...here. * common/config/tilepro/tilepro-common.c: Moved to... * common/config/tilepro/tilepro-common.cc: ...here. * common/config/v850/v850-common.c: Moved to... * common/config/v850/v850-common.cc: ...here. * common/config/vax/vax-common.c: Moved to... * common/config/vax/vax-common.cc: ...here. * common/config/visium/visium-common.c: Moved to... * common/config/visium/visium-common.cc: ...here. * common/config/xstormy16/xstormy16-common.c: Moved to... * common/config/xstormy16/xstormy16-common.cc: ...here. * common/config/xtensa/xtensa-common.c: Moved to... * common/config/xtensa/xtensa-common.cc: ...here. * compare-elim.c: Moved to... * compare-elim.cc: ...here. * config/aarch64/aarch64-bti-insert.c: Moved to... * config/aarch64/aarch64-bti-insert.cc: ...here. * config/aarch64/aarch64-builtins.c: Moved to... * config/aarch64/aarch64-builtins.cc: ...here. * config/aarch64/aarch64-c.c: Moved to... * config/aarch64/aarch64-c.cc: ...here. * config/aarch64/aarch64-d.c: Moved to... * config/aarch64/aarch64-d.cc: ...here. * config/aarch64/aarch64.c: Moved to... * config/aarch64/aarch64.cc: ...here. * config/aarch64/cortex-a57-fma-steering.c: Moved to... * config/aarch64/cortex-a57-fma-steering.cc: ...here. * config/aarch64/driver-aarch64.c: Moved to... * config/aarch64/driver-aarch64.cc: ...here. * config/aarch64/falkor-tag-collision-avoidance.c: Moved to... * config/aarch64/falkor-tag-collision-avoidance.cc: ...here. * config/aarch64/host-aarch64-darwin.c: Moved to... * config/aarch64/host-aarch64-darwin.cc: ...here. * config/alpha/alpha.c: Moved to... * config/alpha/alpha.cc: ...here. * config/alpha/driver-alpha.c: Moved to... * config/alpha/driver-alpha.cc: ...here. * config/arc/arc-c.c: Moved to... * config/arc/arc-c.cc: ...here. * config/arc/arc.c: Moved to... * config/arc/arc.cc: ...here. * config/arc/driver-arc.c: Moved to... * config/arc/driver-arc.cc: ...here. * config/arm/aarch-common.c: Moved to... * config/arm/aarch-common.cc: ...here. * config/arm/arm-builtins.c: Moved to... * config/arm/arm-builtins.cc: ...here. * config/arm/arm-c.c: Moved to... * config/arm/arm-c.cc: ...here. * config/arm/arm-d.c: Moved to... * config/arm/arm-d.cc: ...here. * config/arm/arm.c: Moved to... * config/arm/arm.cc: ...here. * config/arm/driver-arm.c: Moved to... * config/arm/driver-arm.cc: ...here. * config/avr/avr-c.c: Moved to... * config/avr/avr-c.cc: ...here. * config/avr/avr-devices.c: Moved to... * config/avr/avr-devices.cc: ...here. * config/avr/avr-log.c: Moved to... * config/avr/avr-log.cc: ...here. * config/avr/avr.c: Moved to... * config/avr/avr.cc: ...here. * config/avr/driver-avr.c: Moved to... * config/avr/driver-avr.cc: ...here. * config/avr/gen-avr-mmcu-specs.c: Moved to... * config/avr/gen-avr-mmcu-specs.cc: ...here. * config/avr/gen-avr-mmcu-texi.c: Moved to... * config/avr/gen-avr-mmcu-texi.cc: ...here. * config/bfin/bfin.c: Moved to... * config/bfin/bfin.cc: ...here. * config/bpf/bpf.c: Moved to... * config/bpf/bpf.cc: ...here. * config/bpf/coreout.c: Moved to... * config/bpf/coreout.cc: ...here. * config/c6x/c6x.c: Moved to... * config/c6x/c6x.cc: ...here. * config/cr16/cr16.c: Moved to... * config/cr16/cr16.cc: ...here. * config/cris/cris.c: Moved to... * config/cris/cris.cc: ...here. * config/csky/csky.c: Moved to... * config/csky/csky.cc: ...here. * config/darwin-c.c: Moved to... * config/darwin-c.cc: ...here. * config/darwin-d.c: Moved to... * config/darwin-d.cc: ...here. * config/darwin-driver.c: Moved to... * config/darwin-driver.cc: ...here. * config/darwin-f.c: Moved to... * config/darwin-f.cc: ...here. * config/darwin.c: Moved to... * config/darwin.cc: ...here. * config/default-c.c: Moved to... * config/default-c.cc: ...here. * config/default-d.c: Moved to... * config/default-d.cc: ...here. * config/dragonfly-d.c: Moved to... * config/dragonfly-d.cc: ...here. * config/epiphany/epiphany.c: Moved to... * config/epiphany/epiphany.cc: ...here. * config/epiphany/mode-switch-use.c: Moved to... * config/epiphany/mode-switch-use.cc: ...here. * config/epiphany/resolve-sw-modes.c: Moved to... * config/epiphany/resolve-sw-modes.cc: ...here. * config/fr30/fr30.c: Moved to... * config/fr30/fr30.cc: ...here. * config/freebsd-d.c: Moved to... * config/freebsd-d.cc: ...here. * config/frv/frv.c: Moved to... * config/frv/frv.cc: ...here. * config/ft32/ft32.c: Moved to... * config/ft32/ft32.cc: ...here. * config/gcn/driver-gcn.c: Moved to... * config/gcn/driver-gcn.cc: ...here. * config/gcn/gcn-run.c: Moved to... * config/gcn/gcn-run.cc: ...here. * config/gcn/gcn-tree.c: Moved to... * config/gcn/gcn-tree.cc: ...here. * config/gcn/gcn.c: Moved to... * config/gcn/gcn.cc: ...here. * config/gcn/mkoffload.c: Moved to... * config/gcn/mkoffload.cc: ...here. * config/glibc-c.c: Moved to... * config/glibc-c.cc: ...here. * config/glibc-d.c: Moved to... * config/glibc-d.cc: ...here. * config/h8300/h8300.c: Moved to... * config/h8300/h8300.cc: ...here. * config/host-darwin.c: Moved to... * config/host-darwin.cc: ...here. * config/host-hpux.c: Moved to... * config/host-hpux.cc: ...here. * config/host-linux.c: Moved to... * config/host-linux.cc: ...here. * config/host-netbsd.c: Moved to... * config/host-netbsd.cc: ...here. * config/host-openbsd.c: Moved to... * config/host-openbsd.cc: ...here. * config/host-solaris.c: Moved to... * config/host-solaris.cc: ...here. * config/i386/djgpp.c: Moved to... * config/i386/djgpp.cc: ...here. * config/i386/driver-i386.c: Moved to... * config/i386/driver-i386.cc: ...here. * config/i386/driver-mingw32.c: Moved to... * config/i386/driver-mingw32.cc: ...here. * config/i386/gnu-property.c: Moved to... * config/i386/gnu-property.cc: ...here. * config/i386/host-cygwin.c: Moved to... * config/i386/host-cygwin.cc: ...here. * config/i386/host-i386-darwin.c: Moved to... * config/i386/host-i386-darwin.cc: ...here. * config/i386/host-mingw32.c: Moved to... * config/i386/host-mingw32.cc: ...here. * config/i386/i386-builtins.c: Moved to... * config/i386/i386-builtins.cc: ...here. * config/i386/i386-c.c: Moved to... * config/i386/i386-c.cc: ...here. * config/i386/i386-d.c: Moved to... * config/i386/i386-d.cc: ...here. * config/i386/i386-expand.c: Moved to... * config/i386/i386-expand.cc: ...here. * config/i386/i386-features.c: Moved to... * config/i386/i386-features.cc: ...here. * config/i386/i386-options.c: Moved to... * config/i386/i386-options.cc: ...here. * config/i386/i386.c: Moved to... * config/i386/i386.cc: ...here. * config/i386/intelmic-mkoffload.c: Moved to... * config/i386/intelmic-mkoffload.cc: ...here. * config/i386/msformat-c.c: Moved to... * config/i386/msformat-c.cc: ...here. * config/i386/winnt-cxx.c: Moved to... * config/i386/winnt-cxx.cc: ...here. * config/i386/winnt-d.c: Moved to... * config/i386/winnt-d.cc: ...here. * config/i386/winnt-stubs.c: Moved to... * config/i386/winnt-stubs.cc: ...here. * config/i386/winnt.c: Moved to... * config/i386/winnt.cc: ...here. * config/i386/x86-tune-sched-atom.c: Moved to... * config/i386/x86-tune-sched-atom.cc: ...here. * config/i386/x86-tune-sched-bd.c: Moved to... * config/i386/x86-tune-sched-bd.cc: ...here. * config/i386/x86-tune-sched-core.c: Moved to... * config/i386/x86-tune-sched-core.cc: ...here. * config/i386/x86-tune-sched.c: Moved to... * config/i386/x86-tune-sched.cc: ...here. * config/ia64/ia64-c.c: Moved to... * config/ia64/ia64-c.cc: ...here. * config/ia64/ia64.c: Moved to... * config/ia64/ia64.cc: ...here. * config/iq2000/iq2000.c: Moved to... * config/iq2000/iq2000.cc: ...here. * config/linux.c: Moved to... * config/linux.cc: ...here. * config/lm32/lm32.c: Moved to... * config/lm32/lm32.cc: ...here. * config/m32c/m32c-pragma.c: Moved to... * config/m32c/m32c-pragma.cc: ...here. * config/m32c/m32c.c: Moved to... * config/m32c/m32c.cc: ...here. * config/m32r/m32r.c: Moved to... * config/m32r/m32r.cc: ...here. * config/m68k/m68k.c: Moved to... * config/m68k/m68k.cc: ...here. * config/mcore/mcore.c: Moved to... * config/mcore/mcore.cc: ...here. * config/microblaze/microblaze-c.c: Moved to... * config/microblaze/microblaze-c.cc: ...here. * config/microblaze/microblaze.c: Moved to... * config/microblaze/microblaze.cc: ...here. * config/mips/driver-native.c: Moved to... * config/mips/driver-native.cc: ...here. * config/mips/frame-header-opt.c: Moved to... * config/mips/frame-header-opt.cc: ...here. * config/mips/mips-d.c: Moved to... * config/mips/mips-d.cc: ...here. * config/mips/mips.c: Moved to... * config/mips/mips.cc: ...here. * config/mmix/mmix.c: Moved to... * config/mmix/mmix.cc: ...here. * config/mn10300/mn10300.c: Moved to... * config/mn10300/mn10300.cc: ...here. * config/moxie/moxie.c: Moved to... * config/moxie/moxie.cc: ...here. * config/msp430/driver-msp430.c: Moved to... * config/msp430/driver-msp430.cc: ...here. * config/msp430/msp430-c.c: Moved to... * config/msp430/msp430-c.cc: ...here. * config/msp430/msp430-devices.c: Moved to... * config/msp430/msp430-devices.cc: ...here. * config/msp430/msp430.c: Moved to... * config/msp430/msp430.cc: ...here. * config/nds32/nds32-cost.c: Moved to... * config/nds32/nds32-cost.cc: ...here. * config/nds32/nds32-fp-as-gp.c: Moved to... * config/nds32/nds32-fp-as-gp.cc: ...here. * config/nds32/nds32-intrinsic.c: Moved to... * config/nds32/nds32-intrinsic.cc: ...here. * config/nds32/nds32-isr.c: Moved to... * config/nds32/nds32-isr.cc: ...here. * config/nds32/nds32-md-auxiliary.c: Moved to... * config/nds32/nds32-md-auxiliary.cc: ...here. * config/nds32/nds32-memory-manipulation.c: Moved to... * config/nds32/nds32-memory-manipulation.cc: ...here. * config/nds32/nds32-pipelines-auxiliary.c: Moved to... * config/nds32/nds32-pipelines-auxiliary.cc: ...here. * config/nds32/nds32-predicates.c: Moved to... * config/nds32/nds32-predicates.cc: ...here. * config/nds32/nds32-relax-opt.c: Moved to... * config/nds32/nds32-relax-opt.cc: ...here. * config/nds32/nds32-utils.c: Moved to... * config/nds32/nds32-utils.cc: ...here. * config/nds32/nds32.c: Moved to... * config/nds32/nds32.cc: ...here. * config/netbsd-d.c: Moved to... * config/netbsd-d.cc: ...here. * config/netbsd.c: Moved to... * config/netbsd.cc: ...here. * config/nios2/nios2.c: Moved to... * config/nios2/nios2.cc: ...here. * config/nvptx/mkoffload.c: Moved to... * config/nvptx/mkoffload.cc: ...here. * config/nvptx/nvptx-c.c: Moved to... * config/nvptx/nvptx-c.cc: ...here. * config/nvptx/nvptx.c: Moved to... * config/nvptx/nvptx.cc: ...here. * config/openbsd-d.c: Moved to... * config/openbsd-d.cc: ...here. * config/or1k/or1k.c: Moved to... * config/or1k/or1k.cc: ...here. * config/pa/pa-d.c: Moved to... * config/pa/pa-d.cc: ...here. * config/pa/pa.c: Moved to... * config/pa/pa.cc: ...here. * config/pdp11/pdp11.c: Moved to... * config/pdp11/pdp11.cc: ...here. * config/pru/pru-passes.c: Moved to... * config/pru/pru-passes.cc: ...here. * config/pru/pru-pragma.c: Moved to... * config/pru/pru-pragma.cc: ...here. * config/pru/pru.c: Moved to... * config/pru/pru.cc: ...here. * config/riscv/riscv-builtins.c: Moved to... * config/riscv/riscv-builtins.cc: ...here. * config/riscv/riscv-c.c: Moved to... * config/riscv/riscv-c.cc: ...here. * config/riscv/riscv-d.c: Moved to... * config/riscv/riscv-d.cc: ...here. * config/riscv/riscv-shorten-memrefs.c: Moved to... * config/riscv/riscv-shorten-memrefs.cc: ...here. * config/riscv/riscv-sr.c: Moved to... * config/riscv/riscv-sr.cc: ...here. * config/riscv/riscv.c: Moved to... * config/riscv/riscv.cc: ...here. * config/rl78/rl78-c.c: Moved to... * config/rl78/rl78-c.cc: ...here. * config/rl78/rl78.c: Moved to... * config/rl78/rl78.cc: ...here. * config/rs6000/driver-rs6000.c: Moved to... * config/rs6000/driver-rs6000.cc: ...here. * config/rs6000/host-darwin.c: Moved to... * config/rs6000/host-darwin.cc: ...here. * config/rs6000/host-ppc64-darwin.c: Moved to... * config/rs6000/host-ppc64-darwin.cc: ...here. * config/rs6000/rbtree.c: Moved to... * config/rs6000/rbtree.cc: ...here. * config/rs6000/rs6000-c.c: Moved to... * config/rs6000/rs6000-c.cc: ...here. * config/rs6000/rs6000-call.c: Moved to... * config/rs6000/rs6000-call.cc: ...here. * config/rs6000/rs6000-d.c: Moved to... * config/rs6000/rs6000-d.cc: ...here. * config/rs6000/rs6000-gen-builtins.c: Moved to... * config/rs6000/rs6000-gen-builtins.cc: ...here. * config/rs6000/rs6000-linux.c: Moved to... * config/rs6000/rs6000-linux.cc: ...here. * config/rs6000/rs6000-logue.c: Moved to... * config/rs6000/rs6000-logue.cc: ...here. * config/rs6000/rs6000-p8swap.c: Moved to... * config/rs6000/rs6000-p8swap.cc: ...here. * config/rs6000/rs6000-pcrel-opt.c: Moved to... * config/rs6000/rs6000-pcrel-opt.cc: ...here. * config/rs6000/rs6000-string.c: Moved to... * config/rs6000/rs6000-string.cc: ...here. * config/rs6000/rs6000.c: Moved to... * config/rs6000/rs6000.cc: ...here. * config/rx/rx.c: Moved to... * config/rx/rx.cc: ...here. * config/s390/driver-native.c: Moved to... * config/s390/driver-native.cc: ...here. * config/s390/s390-c.c: Moved to... * config/s390/s390-c.cc: ...here. * config/s390/s390-d.c: Moved to... * config/s390/s390-d.cc: ...here. * config/s390/s390.c: Moved to... * config/s390/s390.cc: ...here. * config/sh/divtab-sh4-300.c: Moved to... * config/sh/divtab-sh4-300.cc: ...here. * config/sh/divtab-sh4.c: Moved to... * config/sh/divtab-sh4.cc: ...here. * config/sh/divtab.c: Moved to... * config/sh/divtab.cc: ...here. * config/sh/sh-c.c: Moved to... * config/sh/sh-c.cc: ...here. * config/sh/sh.c: Moved to... * config/sh/sh.cc: ...here. * config/sol2-c.c: Moved to... * config/sol2-c.cc: ...here. * config/sol2-cxx.c: Moved to... * config/sol2-cxx.cc: ...here. * config/sol2-d.c: Moved to... * config/sol2-d.cc: ...here. * config/sol2-stubs.c: Moved to... * config/sol2-stubs.cc: ...here. * config/sol2.c: Moved to... * config/sol2.cc: ...here. * config/sparc/driver-sparc.c: Moved to... * config/sparc/driver-sparc.cc: ...here. * config/sparc/sparc-c.c: Moved to... * config/sparc/sparc-c.cc: ...here. * config/sparc/sparc-d.c: Moved to... * config/sparc/sparc-d.cc: ...here. * config/sparc/sparc.c: Moved to... * config/sparc/sparc.cc: ...here. * config/stormy16/stormy16.c: Moved to... * config/stormy16/stormy16.cc: ...here. * config/tilegx/mul-tables.c: Moved to... * config/tilegx/mul-tables.cc: ...here. * config/tilegx/tilegx-c.c: Moved to... * config/tilegx/tilegx-c.cc: ...here. * config/tilegx/tilegx.c: Moved to... * config/tilegx/tilegx.cc: ...here. * config/tilepro/mul-tables.c: Moved to... * config/tilepro/mul-tables.cc: ...here. * config/tilepro/tilepro-c.c: Moved to... * config/tilepro/tilepro-c.cc: ...here. * config/tilepro/tilepro.c: Moved to... * config/tilepro/tilepro.cc: ...here. * config/v850/v850-c.c: Moved to... * config/v850/v850-c.cc: ...here. * config/v850/v850.c: Moved to... * config/v850/v850.cc: ...here. * config/vax/vax.c: Moved to... * config/vax/vax.cc: ...here. * config/visium/visium.c: Moved to... * config/visium/visium.cc: ...here. * config/vms/vms-c.c: Moved to... * config/vms/vms-c.cc: ...here. * config/vms/vms-f.c: Moved to... * config/vms/vms-f.cc: ...here. * config/vms/vms.c: Moved to... * config/vms/vms.cc: ...here. * config/vxworks-c.c: Moved to... * config/vxworks-c.cc: ...here. * config/vxworks.c: Moved to... * config/vxworks.cc: ...here. * config/winnt-c.c: Moved to... * config/winnt-c.cc: ...here. * config/xtensa/xtensa.c: Moved to... * config/xtensa/xtensa.cc: ...here. * context.c: Moved to... * context.cc: ...here. * convert.c: Moved to... * convert.cc: ...here. * coverage.c: Moved to... * coverage.cc: ...here. * cppbuiltin.c: Moved to... * cppbuiltin.cc: ...here. * cppdefault.c: Moved to... * cppdefault.cc: ...here. * cprop.c: Moved to... * cprop.cc: ...here. * cse.c: Moved to... * cse.cc: ...here. * cselib.c: Moved to... * cselib.cc: ...here. * ctfc.c: Moved to... * ctfc.cc: ...here. * ctfout.c: Moved to... * ctfout.cc: ...here. * data-streamer-in.c: Moved to... * data-streamer-in.cc: ...here. * data-streamer-out.c: Moved to... * data-streamer-out.cc: ...here. * data-streamer.c: Moved to... * data-streamer.cc: ...here. * dbgcnt.c: Moved to... * dbgcnt.cc: ...here. * dbxout.c: Moved to... * dbxout.cc: ...here. * dce.c: Moved to... * dce.cc: ...here. * ddg.c: Moved to... * ddg.cc: ...here. * debug.c: Moved to... * debug.cc: ...here. * df-core.c: Moved to... * df-core.cc: ...here. * df-problems.c: Moved to... * df-problems.cc: ...here. * df-scan.c: Moved to... * df-scan.cc: ...here. * dfp.c: Moved to... * dfp.cc: ...here. * diagnostic-color.c: Moved to... * diagnostic-color.cc: ...here. * diagnostic-show-locus.c: Moved to... * diagnostic-show-locus.cc: ...here. * diagnostic-spec.c: Moved to... * diagnostic-spec.cc: ...here. * diagnostic.c: Moved to... * diagnostic.cc: ...here. * dojump.c: Moved to... * dojump.cc: ...here. * dominance.c: Moved to... * dominance.cc: ...here. * domwalk.c: Moved to... * domwalk.cc: ...here. * double-int.c: Moved to... * double-int.cc: ...here. * dse.c: Moved to... * dse.cc: ...here. * dumpfile.c: Moved to... * dumpfile.cc: ...here. * dwarf2asm.c: Moved to... * dwarf2asm.cc: ...here. * dwarf2cfi.c: Moved to... * dwarf2cfi.cc: ...here. * dwarf2ctf.c: Moved to... * dwarf2ctf.cc: ...here. * dwarf2out.c: Moved to... * dwarf2out.cc: ...here. * early-remat.c: Moved to... * early-remat.cc: ...here. * edit-context.c: Moved to... * edit-context.cc: ...here. * emit-rtl.c: Moved to... * emit-rtl.cc: ...here. * errors.c: Moved to... * errors.cc: ...here. * et-forest.c: Moved to... * et-forest.cc: ...here. * except.c: Moved to... * except.cc: ...here. * explow.c: Moved to... * explow.cc: ...here. * expmed.c: Moved to... * expmed.cc: ...here. * expr.c: Moved to... * expr.cc: ...here. * fibonacci_heap.c: Moved to... * fibonacci_heap.cc: ...here. * file-find.c: Moved to... * file-find.cc: ...here. * file-prefix-map.c: Moved to... * file-prefix-map.cc: ...here. * final.c: Moved to... * final.cc: ...here. * fixed-value.c: Moved to... * fixed-value.cc: ...here. * fold-const-call.c: Moved to... * fold-const-call.cc: ...here. * fold-const.c: Moved to... * fold-const.cc: ...here. * fp-test.c: Moved to... * fp-test.cc: ...here. * function-tests.c: Moved to... * function-tests.cc: ...here. * function.c: Moved to... * function.cc: ...here. * fwprop.c: Moved to... * fwprop.cc: ...here. * gcc-ar.c: Moved to... * gcc-ar.cc: ...here. * gcc-main.c: Moved to... * gcc-main.cc: ...here. * gcc-rich-location.c: Moved to... * gcc-rich-location.cc: ...here. * gcc.c: Moved to... * gcc.cc: ...here. * gcov-dump.c: Moved to... * gcov-dump.cc: ...here. * gcov-io.c: Moved to... * gcov-io.cc: ...here. * gcov-tool.c: Moved to... * gcov-tool.cc: ...here. * gcov.c: Moved to... * gcov.cc: ...here. * gcse-common.c: Moved to... * gcse-common.cc: ...here. * gcse.c: Moved to... * gcse.cc: ...here. * genattr-common.c: Moved to... * genattr-common.cc: ...here. * genattr.c: Moved to... * genattr.cc: ...here. * genattrtab.c: Moved to... * genattrtab.cc: ...here. * genautomata.c: Moved to... * genautomata.cc: ...here. * gencfn-macros.c: Moved to... * gencfn-macros.cc: ...here. * gencheck.c: Moved to... * gencheck.cc: ...here. * genchecksum.c: Moved to... * genchecksum.cc: ...here. * gencodes.c: Moved to... * gencodes.cc: ...here. * genconditions.c: Moved to... * genconditions.cc: ...here. * genconfig.c: Moved to... * genconfig.cc: ...here. * genconstants.c: Moved to... * genconstants.cc: ...here. * genemit.c: Moved to... * genemit.cc: ...here. * genenums.c: Moved to... * genenums.cc: ...here. * generic-match-head.c: Moved to... * generic-match-head.cc: ...here. * genextract.c: Moved to... * genextract.cc: ...here. * genflags.c: Moved to... * genflags.cc: ...here. * gengenrtl.c: Moved to... * gengenrtl.cc: ...here. * gengtype-parse.c: Moved to... * gengtype-parse.cc: ...here. * gengtype-state.c: Moved to... * gengtype-state.cc: ...here. * gengtype.c: Moved to... * gengtype.cc: ...here. * genhooks.c: Moved to... * genhooks.cc: ...here. * genmatch.c: Moved to... * genmatch.cc: ...here. * genmddeps.c: Moved to... * genmddeps.cc: ...here. * genmddump.c: Moved to... * genmddump.cc: ...here. * genmodes.c: Moved to... * genmodes.cc: ...here. * genopinit.c: Moved to... * genopinit.cc: ...here. * genoutput.c: Moved to... * genoutput.cc: ...here. * genpeep.c: Moved to... * genpeep.cc: ...here. * genpreds.c: Moved to... * genpreds.cc: ...here. * genrecog.c: Moved to... * genrecog.cc: ...here. * gensupport.c: Moved to... * gensupport.cc: ...here. * gentarget-def.c: Moved to... * gentarget-def.cc: ...here. * genversion.c: Moved to... * genversion.cc: ...here. * ggc-common.c: Moved to... * ggc-common.cc: ...here. * ggc-none.c: Moved to... * ggc-none.cc: ...here. * ggc-page.c: Moved to... * ggc-page.cc: ...here. * ggc-tests.c: Moved to... * ggc-tests.cc: ...here. * gimple-builder.c: Moved to... * gimple-builder.cc: ...here. * gimple-expr.c: Moved to... * gimple-expr.cc: ...here. * gimple-fold.c: Moved to... * gimple-fold.cc: ...here. * gimple-iterator.c: Moved to... * gimple-iterator.cc: ...here. * gimple-laddress.c: Moved to... * gimple-laddress.cc: ...here. * gimple-loop-jam.c: Moved to... * gimple-loop-jam.cc: ...here. * gimple-low.c: Moved to... * gimple-low.cc: ...here. * gimple-match-head.c: Moved to... * gimple-match-head.cc: ...here. * gimple-pretty-print.c: Moved to... * gimple-pretty-print.cc: ...here. * gimple-ssa-backprop.c: Moved to... * gimple-ssa-backprop.cc: ...here. * gimple-ssa-evrp-analyze.c: Moved to... * gimple-ssa-evrp-analyze.cc: ...here. * gimple-ssa-evrp.c: Moved to... * gimple-ssa-evrp.cc: ...here. * gimple-ssa-isolate-paths.c: Moved to... * gimple-ssa-isolate-paths.cc: ...here. * gimple-ssa-nonnull-compare.c: Moved to... * gimple-ssa-nonnull-compare.cc: ...here. * gimple-ssa-split-paths.c: Moved to... * gimple-ssa-split-paths.cc: ...here. * gimple-ssa-sprintf.c: Moved to... * gimple-ssa-sprintf.cc: ...here. * gimple-ssa-store-merging.c: Moved to... * gimple-ssa-store-merging.cc: ...here. * gimple-ssa-strength-reduction.c: Moved to... * gimple-ssa-strength-reduction.cc: ...here. * gimple-ssa-warn-alloca.c: Moved to... * gimple-ssa-warn-alloca.cc: ...here. * gimple-ssa-warn-restrict.c: Moved to... * gimple-ssa-warn-restrict.cc: ...here. * gimple-streamer-in.c: Moved to... * gimple-streamer-in.cc: ...here. * gimple-streamer-out.c: Moved to... * gimple-streamer-out.cc: ...here. * gimple-walk.c: Moved to... * gimple-walk.cc: ...here. * gimple-warn-recursion.c: Moved to... * gimple-warn-recursion.cc: ...here. * gimple.c: Moved to... * gimple.cc: ...here. * gimplify-me.c: Moved to... * gimplify-me.cc: ...here. * gimplify.c: Moved to... * gimplify.cc: ...here. * godump.c: Moved to... * godump.cc: ...here. * graph.c: Moved to... * graph.cc: ...here. * graphds.c: Moved to... * graphds.cc: ...here. * graphite-dependences.c: Moved to... * graphite-dependences.cc: ...here. * graphite-isl-ast-to-gimple.c: Moved to... * graphite-isl-ast-to-gimple.cc: ...here. * graphite-optimize-isl.c: Moved to... * graphite-optimize-isl.cc: ...here. * graphite-poly.c: Moved to... * graphite-poly.cc: ...here. * graphite-scop-detection.c: Moved to... * graphite-scop-detection.cc: ...here. * graphite-sese-to-poly.c: Moved to... * graphite-sese-to-poly.cc: ...here. * graphite.c: Moved to... * graphite.cc: ...here. * haifa-sched.c: Moved to... * haifa-sched.cc: ...here. * hash-map-tests.c: Moved to... * hash-map-tests.cc: ...here. * hash-set-tests.c: Moved to... * hash-set-tests.cc: ...here. * hash-table.c: Moved to... * hash-table.cc: ...here. * hooks.c: Moved to... * hooks.cc: ...here. * host-default.c: Moved to... * host-default.cc: ...here. * hw-doloop.c: Moved to... * hw-doloop.cc: ...here. * hwint.c: Moved to... * hwint.cc: ...here. * ifcvt.c: Moved to... * ifcvt.cc: ...here. * inchash.c: Moved to... * inchash.cc: ...here. * incpath.c: Moved to... * incpath.cc: ...here. * init-regs.c: Moved to... * init-regs.cc: ...here. * input.c: Moved to... * input.cc: ...here. * internal-fn.c: Moved to... * internal-fn.cc: ...here. * intl.c: Moved to... * intl.cc: ...here. * ipa-comdats.c: Moved to... * ipa-comdats.cc: ...here. * ipa-cp.c: Moved to... * ipa-cp.cc: ...here. * ipa-devirt.c: Moved to... * ipa-devirt.cc: ...here. * ipa-fnsummary.c: Moved to... * ipa-fnsummary.cc: ...here. * ipa-icf-gimple.c: Moved to... * ipa-icf-gimple.cc: ...here. * ipa-icf.c: Moved to... * ipa-icf.cc: ...here. * ipa-inline-analysis.c: Moved to... * ipa-inline-analysis.cc: ...here. * ipa-inline-transform.c: Moved to... * ipa-inline-transform.cc: ...here. * ipa-inline.c: Moved to... * ipa-inline.cc: ...here. * ipa-modref-tree.c: Moved to... * ipa-modref-tree.cc: ...here. * ipa-modref.c: Moved to... * ipa-modref.cc: ...here. * ipa-param-manipulation.c: Moved to... * ipa-param-manipulation.cc: ...here. * ipa-polymorphic-call.c: Moved to... * ipa-polymorphic-call.cc: ...here. * ipa-predicate.c: Moved to... * ipa-predicate.cc: ...here. * ipa-profile.c: Moved to... * ipa-profile.cc: ...here. * ipa-prop.c: Moved to... * ipa-prop.cc: ...here. * ipa-pure-const.c: Moved to... * ipa-pure-const.cc: ...here. * ipa-ref.c: Moved to... * ipa-ref.cc: ...here. * ipa-reference.c: Moved to... * ipa-reference.cc: ...here. * ipa-split.c: Moved to... * ipa-split.cc: ...here. * ipa-sra.c: Moved to... * ipa-sra.cc: ...here. * ipa-utils.c: Moved to... * ipa-utils.cc: ...here. * ipa-visibility.c: Moved to... * ipa-visibility.cc: ...here. * ipa.c: Moved to... * ipa.cc: ...here. * ira-build.c: Moved to... * ira-build.cc: ...here. * ira-color.c: Moved to... * ira-color.cc: ...here. * ira-conflicts.c: Moved to... * ira-conflicts.cc: ...here. * ira-costs.c: Moved to... * ira-costs.cc: ...here. * ira-emit.c: Moved to... * ira-emit.cc: ...here. * ira-lives.c: Moved to... * ira-lives.cc: ...here. * ira.c: Moved to... * ira.cc: ...here. * jump.c: Moved to... * jump.cc: ...here. * langhooks.c: Moved to... * langhooks.cc: ...here. * lcm.c: Moved to... * lcm.cc: ...here. * lists.c: Moved to... * lists.cc: ...here. * loop-doloop.c: Moved to... * loop-doloop.cc: ...here. * loop-init.c: Moved to... * loop-init.cc: ...here. * loop-invariant.c: Moved to... * loop-invariant.cc: ...here. * loop-iv.c: Moved to... * loop-iv.cc: ...here. * loop-unroll.c: Moved to... * loop-unroll.cc: ...here. * lower-subreg.c: Moved to... * lower-subreg.cc: ...here. * lra-assigns.c: Moved to... * lra-assigns.cc: ...here. * lra-coalesce.c: Moved to... * lra-coalesce.cc: ...here. * lra-constraints.c: Moved to... * lra-constraints.cc: ...here. * lra-eliminations.c: Moved to... * lra-eliminations.cc: ...here. * lra-lives.c: Moved to... * lra-lives.cc: ...here. * lra-remat.c: Moved to... * lra-remat.cc: ...here. * lra-spills.c: Moved to... * lra-spills.cc: ...here. * lra.c: Moved to... * lra.cc: ...here. * lto-cgraph.c: Moved to... * lto-cgraph.cc: ...here. * lto-compress.c: Moved to... * lto-compress.cc: ...here. * lto-opts.c: Moved to... * lto-opts.cc: ...here. * lto-section-in.c: Moved to... * lto-section-in.cc: ...here. * lto-section-out.c: Moved to... * lto-section-out.cc: ...here. * lto-streamer-in.c: Moved to... * lto-streamer-in.cc: ...here. * lto-streamer-out.c: Moved to... * lto-streamer-out.cc: ...here. * lto-streamer.c: Moved to... * lto-streamer.cc: ...here. * lto-wrapper.c: Moved to... * lto-wrapper.cc: ...here. * main.c: Moved to... * main.cc: ...here. * mcf.c: Moved to... * mcf.cc: ...here. * mode-switching.c: Moved to... * mode-switching.cc: ...here. * modulo-sched.c: Moved to... * modulo-sched.cc: ...here. * multiple_target.c: Moved to... * multiple_target.cc: ...here. * omp-expand.c: Moved to... * omp-expand.cc: ...here. * omp-general.c: Moved to... * omp-general.cc: ...here. * omp-low.c: Moved to... * omp-low.cc: ...here. * omp-offload.c: Moved to... * omp-offload.cc: ...here. * omp-simd-clone.c: Moved to... * omp-simd-clone.cc: ...here. * opt-suggestions.c: Moved to... * opt-suggestions.cc: ...here. * optabs-libfuncs.c: Moved to... * optabs-libfuncs.cc: ...here. * optabs-query.c: Moved to... * optabs-query.cc: ...here. * optabs-tree.c: Moved to... * optabs-tree.cc: ...here. * optabs.c: Moved to... * optabs.cc: ...here. * opts-common.c: Moved to... * opts-common.cc: ...here. * opts-global.c: Moved to... * opts-global.cc: ...here. * opts.c: Moved to... * opts.cc: ...here. * passes.c: Moved to... * passes.cc: ...here. * plugin.c: Moved to... * plugin.cc: ...here. * postreload-gcse.c: Moved to... * postreload-gcse.cc: ...here. * postreload.c: Moved to... * postreload.cc: ...here. * predict.c: Moved to... * predict.cc: ...here. * prefix.c: Moved to... * prefix.cc: ...here. * pretty-print.c: Moved to... * pretty-print.cc: ...here. * print-rtl-function.c: Moved to... * print-rtl-function.cc: ...here. * print-rtl.c: Moved to... * print-rtl.cc: ...here. * print-tree.c: Moved to... * print-tree.cc: ...here. * profile-count.c: Moved to... * profile-count.cc: ...here. * profile.c: Moved to... * profile.cc: ...here. * read-md.c: Moved to... * read-md.cc: ...here. * read-rtl-function.c: Moved to... * read-rtl-function.cc: ...here. * read-rtl.c: Moved to... * read-rtl.cc: ...here. * real.c: Moved to... * real.cc: ...here. * realmpfr.c: Moved to... * realmpfr.cc: ...here. * recog.c: Moved to... * recog.cc: ...here. * ree.c: Moved to... * ree.cc: ...here. * reg-stack.c: Moved to... * reg-stack.cc: ...here. * regcprop.c: Moved to... * regcprop.cc: ...here. * reginfo.c: Moved to... * reginfo.cc: ...here. * regrename.c: Moved to... * regrename.cc: ...here. * regstat.c: Moved to... * regstat.cc: ...here. * reload.c: Moved to... * reload.cc: ...here. * reload1.c: Moved to... * reload1.cc: ...here. * reorg.c: Moved to... * reorg.cc: ...here. * resource.c: Moved to... * resource.cc: ...here. * rtl-error.c: Moved to... * rtl-error.cc: ...here. * rtl-tests.c: Moved to... * rtl-tests.cc: ...here. * rtl.c: Moved to... * rtl.cc: ...here. * rtlanal.c: Moved to... * rtlanal.cc: ...here. * rtlhash.c: Moved to... * rtlhash.cc: ...here. * rtlhooks.c: Moved to... * rtlhooks.cc: ...here. * rtx-vector-builder.c: Moved to... * rtx-vector-builder.cc: ...here. * run-rtl-passes.c: Moved to... * run-rtl-passes.cc: ...here. * sancov.c: Moved to... * sancov.cc: ...here. * sanopt.c: Moved to... * sanopt.cc: ...here. * sbitmap.c: Moved to... * sbitmap.cc: ...here. * sched-deps.c: Moved to... * sched-deps.cc: ...here. * sched-ebb.c: Moved to... * sched-ebb.cc: ...here. * sched-rgn.c: Moved to... * sched-rgn.cc: ...here. * sel-sched-dump.c: Moved to... * sel-sched-dump.cc: ...here. * sel-sched-ir.c: Moved to... * sel-sched-ir.cc: ...here. * sel-sched.c: Moved to... * sel-sched.cc: ...here. * selftest-diagnostic.c: Moved to... * selftest-diagnostic.cc: ...here. * selftest-rtl.c: Moved to... * selftest-rtl.cc: ...here. * selftest-run-tests.c: Moved to... * selftest-run-tests.cc: ...here. * selftest.c: Moved to... * selftest.cc: ...here. * sese.c: Moved to... * sese.cc: ...here. * shrink-wrap.c: Moved to... * shrink-wrap.cc: ...here. * simplify-rtx.c: Moved to... * simplify-rtx.cc: ...here. * sparseset.c: Moved to... * sparseset.cc: ...here. * spellcheck-tree.c: Moved to... * spellcheck-tree.cc: ...here. * spellcheck.c: Moved to... * spellcheck.cc: ...here. * sreal.c: Moved to... * sreal.cc: ...here. * stack-ptr-mod.c: Moved to... * stack-ptr-mod.cc: ...here. * statistics.c: Moved to... * statistics.cc: ...here. * stmt.c: Moved to... * stmt.cc: ...here. * stor-layout.c: Moved to... * stor-layout.cc: ...here. * store-motion.c: Moved to... * store-motion.cc: ...here. * streamer-hooks.c: Moved to... * streamer-hooks.cc: ...here. * stringpool.c: Moved to... * stringpool.cc: ...here. * substring-locations.c: Moved to... * substring-locations.cc: ...here. * symtab.c: Moved to... * symtab.cc: ...here. * target-globals.c: Moved to... * target-globals.cc: ...here. * targhooks.c: Moved to... * targhooks.cc: ...here. * timevar.c: Moved to... * timevar.cc: ...here. * toplev.c: Moved to... * toplev.cc: ...here. * tracer.c: Moved to... * tracer.cc: ...here. * trans-mem.c: Moved to... * trans-mem.cc: ...here. * tree-affine.c: Moved to... * tree-affine.cc: ...here. * tree-call-cdce.c: Moved to... * tree-call-cdce.cc: ...here. * tree-cfg.c: Moved to... * tree-cfg.cc: ...here. * tree-cfgcleanup.c: Moved to... * tree-cfgcleanup.cc: ...here. * tree-chrec.c: Moved to... * tree-chrec.cc: ...here. * tree-complex.c: Moved to... * tree-complex.cc: ...here. * tree-data-ref.c: Moved to... * tree-data-ref.cc: ...here. * tree-dfa.c: Moved to... * tree-dfa.cc: ...here. * tree-diagnostic.c: Moved to... * tree-diagnostic.cc: ...here. * tree-dump.c: Moved to... * tree-dump.cc: ...here. * tree-eh.c: Moved to... * tree-eh.cc: ...here. * tree-emutls.c: Moved to... * tree-emutls.cc: ...here. * tree-if-conv.c: Moved to... * tree-if-conv.cc: ...here. * tree-inline.c: Moved to... * tree-inline.cc: ...here. * tree-into-ssa.c: Moved to... * tree-into-ssa.cc: ...here. * tree-iterator.c: Moved to... * tree-iterator.cc: ...here. * tree-loop-distribution.c: Moved to... * tree-loop-distribution.cc: ...here. * tree-nested.c: Moved to... * tree-nested.cc: ...here. * tree-nrv.c: Moved to... * tree-nrv.cc: ...here. * tree-object-size.c: Moved to... * tree-object-size.cc: ...here. * tree-outof-ssa.c: Moved to... * tree-outof-ssa.cc: ...here. * tree-parloops.c: Moved to... * tree-parloops.cc: ...here. * tree-phinodes.c: Moved to... * tree-phinodes.cc: ...here. * tree-predcom.c: Moved to... * tree-predcom.cc: ...here. * tree-pretty-print.c: Moved to... * tree-pretty-print.cc: ...here. * tree-profile.c: Moved to... * tree-profile.cc: ...here. * tree-scalar-evolution.c: Moved to... * tree-scalar-evolution.cc: ...here. * tree-sra.c: Moved to... * tree-sra.cc: ...here. * tree-ssa-address.c: Moved to... * tree-ssa-address.cc: ...here. * tree-ssa-alias.c: Moved to... * tree-ssa-alias.cc: ...here. * tree-ssa-ccp.c: Moved to... * tree-ssa-ccp.cc: ...here. * tree-ssa-coalesce.c: Moved to... * tree-ssa-coalesce.cc: ...here. * tree-ssa-copy.c: Moved to... * tree-ssa-copy.cc: ...here. * tree-ssa-dce.c: Moved to... * tree-ssa-dce.cc: ...here. * tree-ssa-dom.c: Moved to... * tree-ssa-dom.cc: ...here. * tree-ssa-dse.c: Moved to... * tree-ssa-dse.cc: ...here. * tree-ssa-forwprop.c: Moved to... * tree-ssa-forwprop.cc: ...here. * tree-ssa-ifcombine.c: Moved to... * tree-ssa-ifcombine.cc: ...here. * tree-ssa-live.c: Moved to... * tree-ssa-live.cc: ...here. * tree-ssa-loop-ch.c: Moved to... * tree-ssa-loop-ch.cc: ...here. * tree-ssa-loop-im.c: Moved to... * tree-ssa-loop-im.cc: ...here. * tree-ssa-loop-ivcanon.c: Moved to... * tree-ssa-loop-ivcanon.cc: ...here. * tree-ssa-loop-ivopts.c: Moved to... * tree-ssa-loop-ivopts.cc: ...here. * tree-ssa-loop-manip.c: Moved to... * tree-ssa-loop-manip.cc: ...here. * tree-ssa-loop-niter.c: Moved to... * tree-ssa-loop-niter.cc: ...here. * tree-ssa-loop-prefetch.c: Moved to... * tree-ssa-loop-prefetch.cc: ...here. * tree-ssa-loop-split.c: Moved to... * tree-ssa-loop-split.cc: ...here. * tree-ssa-loop-unswitch.c: Moved to... * tree-ssa-loop-unswitch.cc: ...here. * tree-ssa-loop.c: Moved to... * tree-ssa-loop.cc: ...here. * tree-ssa-math-opts.c: Moved to... * tree-ssa-math-opts.cc: ...here. * tree-ssa-operands.c: Moved to... * tree-ssa-operands.cc: ...here. * tree-ssa-phiopt.c: Moved to... * tree-ssa-phiopt.cc: ...here. * tree-ssa-phiprop.c: Moved to... * tree-ssa-phiprop.cc: ...here. * tree-ssa-pre.c: Moved to... * tree-ssa-pre.cc: ...here. * tree-ssa-propagate.c: Moved to... * tree-ssa-propagate.cc: ...here. * tree-ssa-reassoc.c: Moved to... * tree-ssa-reassoc.cc: ...here. * tree-ssa-sccvn.c: Moved to... * tree-ssa-sccvn.cc: ...here. * tree-ssa-scopedtables.c: Moved to... * tree-ssa-scopedtables.cc: ...here. * tree-ssa-sink.c: Moved to... * tree-ssa-sink.cc: ...here. * tree-ssa-strlen.c: Moved to... * tree-ssa-strlen.cc: ...here. * tree-ssa-structalias.c: Moved to... * tree-ssa-structalias.cc: ...here. * tree-ssa-tail-merge.c: Moved to... * tree-ssa-tail-merge.cc: ...here. * tree-ssa-ter.c: Moved to... * tree-ssa-ter.cc: ...here. * tree-ssa-threadbackward.c: Moved to... * tree-ssa-threadbackward.cc: ...here. * tree-ssa-threadedge.c: Moved to... * tree-ssa-threadedge.cc: ...here. * tree-ssa-threadupdate.c: Moved to... * tree-ssa-threadupdate.cc: ...here. * tree-ssa-uncprop.c: Moved to... * tree-ssa-uncprop.cc: ...here. * tree-ssa-uninit.c: Moved to... * tree-ssa-uninit.cc: ...here. * tree-ssa.c: Moved to... * tree-ssa.cc: ...here. * tree-ssanames.c: Moved to... * tree-ssanames.cc: ...here. * tree-stdarg.c: Moved to... * tree-stdarg.cc: ...here. * tree-streamer-in.c: Moved to... * tree-streamer-in.cc: ...here. * tree-streamer-out.c: Moved to... * tree-streamer-out.cc: ...here. * tree-streamer.c: Moved to... * tree-streamer.cc: ...here. * tree-switch-conversion.c: Moved to... * tree-switch-conversion.cc: ...here. * tree-tailcall.c: Moved to... * tree-tailcall.cc: ...here. * tree-vect-data-refs.c: Moved to... * tree-vect-data-refs.cc: ...here. * tree-vect-generic.c: Moved to... * tree-vect-generic.cc: ...here. * tree-vect-loop-manip.c: Moved to... * tree-vect-loop-manip.cc: ...here. * tree-vect-loop.c: Moved to... * tree-vect-loop.cc: ...here. * tree-vect-patterns.c: Moved to... * tree-vect-patterns.cc: ...here. * tree-vect-slp-patterns.c: Moved to... * tree-vect-slp-patterns.cc: ...here. * tree-vect-slp.c: Moved to... * tree-vect-slp.cc: ...here. * tree-vect-stmts.c: Moved to... * tree-vect-stmts.cc: ...here. * tree-vector-builder.c: Moved to... * tree-vector-builder.cc: ...here. * tree-vectorizer.c: Moved to... * tree-vectorizer.cc: ...here. * tree-vrp.c: Moved to... * tree-vrp.cc: ...here. * tree.c: Moved to... * tree.cc: ...here. * tsan.c: Moved to... * tsan.cc: ...here. * typed-splay-tree.c: Moved to... * typed-splay-tree.cc: ...here. * ubsan.c: Moved to... * ubsan.cc: ...here. * valtrack.c: Moved to... * valtrack.cc: ...here. * value-prof.c: Moved to... * value-prof.cc: ...here. * var-tracking.c: Moved to... * var-tracking.cc: ...here. * varasm.c: Moved to... * varasm.cc: ...here. * varpool.c: Moved to... * varpool.cc: ...here. * vec-perm-indices.c: Moved to... * vec-perm-indices.cc: ...here. * vec.c: Moved to... * vec.cc: ...here. * vmsdbgout.c: Moved to... * vmsdbgout.cc: ...here. * vr-values.c: Moved to... * vr-values.cc: ...here. * vtable-verify.c: Moved to... * vtable-verify.cc: ...here. * web.c: Moved to... * web.cc: ...here. * xcoffout.c: Moved to... * xcoffout.cc: ...here. gcc/c-family/ChangeLog: * c-ada-spec.c: Moved to... * c-ada-spec.cc: ...here. * c-attribs.c: Moved to... * c-attribs.cc: ...here. * c-common.c: Moved to... * c-common.cc: ...here. * c-cppbuiltin.c: Moved to... * c-cppbuiltin.cc: ...here. * c-dump.c: Moved to... * c-dump.cc: ...here. * c-format.c: Moved to... * c-format.cc: ...here. * c-gimplify.c: Moved to... * c-gimplify.cc: ...here. * c-indentation.c: Moved to... * c-indentation.cc: ...here. * c-lex.c: Moved to... * c-lex.cc: ...here. * c-omp.c: Moved to... * c-omp.cc: ...here. * c-opts.c: Moved to... * c-opts.cc: ...here. * c-pch.c: Moved to... * c-pch.cc: ...here. * c-ppoutput.c: Moved to... * c-ppoutput.cc: ...here. * c-pragma.c: Moved to... * c-pragma.cc: ...here. * c-pretty-print.c: Moved to... * c-pretty-print.cc: ...here. * c-semantics.c: Moved to... * c-semantics.cc: ...here. * c-ubsan.c: Moved to... * c-ubsan.cc: ...here. * c-warn.c: Moved to... * c-warn.cc: ...here. * cppspec.c: Moved to... * cppspec.cc: ...here. * stub-objc.c: Moved to... * stub-objc.cc: ...here. gcc/c/ChangeLog: * c-aux-info.c: Moved to... * c-aux-info.cc: ...here. * c-convert.c: Moved to... * c-convert.cc: ...here. * c-decl.c: Moved to... * c-decl.cc: ...here. * c-errors.c: Moved to... * c-errors.cc: ...here. * c-fold.c: Moved to... * c-fold.cc: ...here. * c-lang.c: Moved to... * c-lang.cc: ...here. * c-objc-common.c: Moved to... * c-objc-common.cc: ...here. * c-parser.c: Moved to... * c-parser.cc: ...here. * c-typeck.c: Moved to... * c-typeck.cc: ...here. * gccspec.c: Moved to... * gccspec.cc: ...here. * gimple-parser.c: Moved to... * gimple-parser.cc: ...here. gcc/cp/ChangeLog: * call.c: Moved to... * call.cc: ...here. * class.c: Moved to... * class.cc: ...here. * constexpr.c: Moved to... * constexpr.cc: ...here. * cp-gimplify.c: Moved to... * cp-gimplify.cc: ...here. * cp-lang.c: Moved to... * cp-lang.cc: ...here. * cp-objcp-common.c: Moved to... * cp-objcp-common.cc: ...here. * cp-ubsan.c: Moved to... * cp-ubsan.cc: ...here. * cvt.c: Moved to... * cvt.cc: ...here. * cxx-pretty-print.c: Moved to... * cxx-pretty-print.cc: ...here. * decl.c: Moved to... * decl.cc: ...here. * decl2.c: Moved to... * decl2.cc: ...here. * dump.c: Moved to... * dump.cc: ...here. * error.c: Moved to... * error.cc: ...here. * except.c: Moved to... * except.cc: ...here. * expr.c: Moved to... * expr.cc: ...here. * friend.c: Moved to... * friend.cc: ...here. * g++spec.c: Moved to... * g++spec.cc: ...here. * init.c: Moved to... * init.cc: ...here. * lambda.c: Moved to... * lambda.cc: ...here. * lex.c: Moved to... * lex.cc: ...here. * mangle.c: Moved to... * mangle.cc: ...here. * method.c: Moved to... * method.cc: ...here. * name-lookup.c: Moved to... * name-lookup.cc: ...here. * optimize.c: Moved to... * optimize.cc: ...here. * parser.c: Moved to... * parser.cc: ...here. * pt.c: Moved to... * pt.cc: ...here. * ptree.c: Moved to... * ptree.cc: ...here. * rtti.c: Moved to... * rtti.cc: ...here. * search.c: Moved to... * search.cc: ...here. * semantics.c: Moved to... * semantics.cc: ...here. * tree.c: Moved to... * tree.cc: ...here. * typeck.c: Moved to... * typeck.cc: ...here. * typeck2.c: Moved to... * typeck2.cc: ...here. * vtable-class-hierarchy.c: Moved to... * vtable-class-hierarchy.cc: ...here. gcc/fortran/ChangeLog: * arith.c: Moved to... * arith.cc: ...here. * array.c: Moved to... * array.cc: ...here. * bbt.c: Moved to... * bbt.cc: ...here. * check.c: Moved to... * check.cc: ...here. * class.c: Moved to... * class.cc: ...here. * constructor.c: Moved to... * constructor.cc: ...here. * convert.c: Moved to... * convert.cc: ...here. * cpp.c: Moved to... * cpp.cc: ...here. * data.c: Moved to... * data.cc: ...here. * decl.c: Moved to... * decl.cc: ...here. * dependency.c: Moved to... * dependency.cc: ...here. * dump-parse-tree.c: Moved to... * dump-parse-tree.cc: ...here. * error.c: Moved to... * error.cc: ...here. * expr.c: Moved to... * expr.cc: ...here. * f95-lang.c: Moved to... * f95-lang.cc: ...here. * frontend-passes.c: Moved to... * frontend-passes.cc: ...here. * gfortranspec.c: Moved to... * gfortranspec.cc: ...here. * interface.c: Moved to... * interface.cc: ...here. * intrinsic.c: Moved to... * intrinsic.cc: ...here. * io.c: Moved to... * io.cc: ...here. * iresolve.c: Moved to... * iresolve.cc: ...here. * match.c: Moved to... * match.cc: ...here. * matchexp.c: Moved to... * matchexp.cc: ...here. * misc.c: Moved to... * misc.cc: ...here. * module.c: Moved to... * module.cc: ...here. * openmp.c: Moved to... * openmp.cc: ...here. * options.c: Moved to... * options.cc: ...here. * parse.c: Moved to... * parse.cc: ...here. * primary.c: Moved to... * primary.cc: ...here. * resolve.c: Moved to... * resolve.cc: ...here. * scanner.c: Moved to... * scanner.cc: ...here. * simplify.c: Moved to... * simplify.cc: ...here. * st.c: Moved to... * st.cc: ...here. * symbol.c: Moved to... * symbol.cc: ...here. * target-memory.c: Moved to... * target-memory.cc: ...here. * trans-array.c: Moved to... * trans-array.cc: ...here. * trans-common.c: Moved to... * trans-common.cc: ...here. * trans-const.c: Moved to... * trans-const.cc: ...here. * trans-decl.c: Moved to... * trans-decl.cc: ...here. * trans-expr.c: Moved to... * trans-expr.cc: ...here. * trans-intrinsic.c: Moved to... * trans-intrinsic.cc: ...here. * trans-io.c: Moved to... * trans-io.cc: ...here. * trans-openmp.c: Moved to... * trans-openmp.cc: ...here. * trans-stmt.c: Moved to... * trans-stmt.cc: ...here. * trans-types.c: Moved to... * trans-types.cc: ...here. * trans.c: Moved to... * trans.cc: ...here. gcc/go/ChangeLog: * go-backend.c: Moved to... * go-backend.cc: ...here. * go-lang.c: Moved to... * go-lang.cc: ...here. * gospec.c: Moved to... * gospec.cc: ...here. gcc/jit/ChangeLog: * dummy-frontend.c: Moved to... * dummy-frontend.cc: ...here. * jit-builtins.c: Moved to... * jit-builtins.cc: ...here. * jit-logging.c: Moved to... * jit-logging.cc: ...here. * jit-playback.c: Moved to... * jit-playback.cc: ...here. * jit-recording.c: Moved to... * jit-recording.cc: ...here. * jit-result.c: Moved to... * jit-result.cc: ...here. * jit-spec.c: Moved to... * jit-spec.cc: ...here. * jit-tempdir.c: Moved to... * jit-tempdir.cc: ...here. * jit-w32.c: Moved to... * jit-w32.cc: ...here. * libgccjit.c: Moved to... * libgccjit.cc: ...here. gcc/lto/ChangeLog: * common.c: Moved to... * common.cc: ...here. * lto-common.c: Moved to... * lto-common.cc: ...here. * lto-dump.c: Moved to... * lto-dump.cc: ...here. * lto-lang.c: Moved to... * lto-lang.cc: ...here. * lto-object.c: Moved to... * lto-object.cc: ...here. * lto-partition.c: Moved to... * lto-partition.cc: ...here. * lto-symtab.c: Moved to... * lto-symtab.cc: ...here. * lto.c: Moved to... * lto.cc: ...here. gcc/objc/ChangeLog: * objc-act.c: Moved to... * objc-act.cc: ...here. * objc-encoding.c: Moved to... * objc-encoding.cc: ...here. * objc-gnu-runtime-abi-01.c: Moved to... * objc-gnu-runtime-abi-01.cc: ...here. * objc-lang.c: Moved to... * objc-lang.cc: ...here. * objc-map.c: Moved to... * objc-map.cc: ...here. * objc-next-runtime-abi-01.c: Moved to... * objc-next-runtime-abi-01.cc: ...here. * objc-next-runtime-abi-02.c: Moved to... * objc-next-runtime-abi-02.cc: ...here. * objc-runtime-shared-support.c: Moved to... * objc-runtime-shared-support.cc: ...here. gcc/objcp/ChangeLog: * objcp-decl.c: Moved to... * objcp-decl.cc: ...here. * objcp-lang.c: Moved to... * objcp-lang.cc: ...here. libcpp/ChangeLog: * charset.c: Moved to... * charset.cc: ...here. * directives.c: Moved to... * directives.cc: ...here. * errors.c: Moved to... * errors.cc: ...here. * expr.c: Moved to... * expr.cc: ...here. * files.c: Moved to... * files.cc: ...here. * identifiers.c: Moved to... * identifiers.cc: ...here. * init.c: Moved to... * init.cc: ...here. * lex.c: Moved to... * lex.cc: ...here. * line-map.c: Moved to... * line-map.cc: ...here. * macro.c: Moved to... * macro.cc: ...here. * makeucnid.c: Moved to... * makeucnid.cc: ...here. * mkdeps.c: Moved to... * mkdeps.cc: ...here. * pch.c: Moved to... * pch.cc: ...here. * symtab.c: Moved to... * symtab.cc: ...here. * traditional.c: Moved to... * traditional.cc: ...here.
Diffstat (limited to 'gcc/tree-sra.c')
-rw-r--r--gcc/tree-sra.c4794
1 files changed, 0 insertions, 4794 deletions
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
deleted file mode 100644
index e0ea2c7..0000000
--- a/gcc/tree-sra.c
+++ /dev/null
@@ -1,4794 +0,0 @@
-/* Scalar Replacement of Aggregates (SRA) converts some structure
- references into scalar references, exposing them to the scalar
- optimizers.
- Copyright (C) 2008-2022 Free Software Foundation, Inc.
- Contributed by Martin Jambor <mjambor@suse.cz>
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* This file implements Scalar Reduction of Aggregates (SRA). SRA is run
- twice, once in the early stages of compilation (early SRA) and once in the
- late stages (late SRA). The aim of both is to turn references to scalar
- parts of aggregates into uses of independent scalar variables.
-
- The two passes are nearly identical, the only difference is that early SRA
- does not scalarize unions which are used as the result in a GIMPLE_RETURN
- statement because together with inlining this can lead to weird type
- conversions.
-
- Both passes operate in four stages:
-
- 1. The declarations that have properties which make them candidates for
- scalarization are identified in function find_var_candidates(). The
- candidates are stored in candidate_bitmap.
-
- 2. The function body is scanned. In the process, declarations which are
- used in a manner that prevent their scalarization are removed from the
- candidate bitmap. More importantly, for every access into an aggregate,
- an access structure (struct access) is created by create_access() and
- stored in a vector associated with the aggregate. Among other
- information, the aggregate declaration, the offset and size of the access
- and its type are stored in the structure.
-
- On a related note, assign_link structures are created for every assign
- statement between candidate aggregates and attached to the related
- accesses.
-
- 3. The vectors of accesses are analyzed. They are first sorted according to
- their offset and size and then scanned for partially overlapping accesses
- (i.e. those which overlap but one is not entirely within another). Such
- an access disqualifies the whole aggregate from being scalarized.
-
- If there is no such inhibiting overlap, a representative access structure
- is chosen for every unique combination of offset and size. Afterwards,
- the pass builds a set of trees from these structures, in which children
- of an access are within their parent (in terms of offset and size).
-
- Then accesses are propagated whenever possible (i.e. in cases when it
- does not create a partially overlapping access) across assign_links from
- the right hand side to the left hand side.
-
- Then the set of trees for each declaration is traversed again and those
- accesses which should be replaced by a scalar are identified.
-
- 4. The function is traversed again, and for every reference into an
- aggregate that has some component which is about to be scalarized,
- statements are amended and new statements are created as necessary.
- Finally, if a parameter got scalarized, the scalar replacements are
- initialized with values from respective parameter aggregates. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "backend.h"
-#include "target.h"
-#include "rtl.h"
-#include "tree.h"
-#include "gimple.h"
-#include "predict.h"
-#include "alloc-pool.h"
-#include "tree-pass.h"
-#include "ssa.h"
-#include "cgraph.h"
-#include "gimple-pretty-print.h"
-#include "alias.h"
-#include "fold-const.h"
-#include "tree-eh.h"
-#include "stor-layout.h"
-#include "gimplify.h"
-#include "gimple-iterator.h"
-#include "gimplify-me.h"
-#include "gimple-walk.h"
-#include "tree-cfg.h"
-#include "tree-dfa.h"
-#include "tree-ssa.h"
-#include "dbgcnt.h"
-#include "builtins.h"
-#include "tree-sra.h"
-#include "opts.h"
-
-/* Enumeration of all aggregate reductions we can do. */
-enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
- SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
- SRA_MODE_INTRA }; /* late intraprocedural SRA */
-
-/* Global variable describing which aggregate reduction we are performing at
- the moment. */
-static enum sra_mode sra_mode;
-
-struct assign_link;
-
-/* ACCESS represents each access to an aggregate variable (as a whole or a
- part). It can also represent a group of accesses that refer to exactly the
- same fragment of an aggregate (i.e. those that have exactly the same offset
- and size). Such representatives for a single aggregate, once determined,
- are linked in a linked list and have the group fields set.
-
- Moreover, when doing intraprocedural SRA, a tree is built from those
- representatives (by the means of first_child and next_sibling pointers), in
- which all items in a subtree are "within" the root, i.e. their offset is
- greater or equal to offset of the root and offset+size is smaller or equal
- to offset+size of the root. Children of an access are sorted by offset.
-
- Note that accesses to parts of vector and complex number types always
- represented by an access to the whole complex number or a vector. It is a
- duty of the modifying functions to replace them appropriately. */
-
-struct access
-{
- /* Values returned by `get_ref_base_and_extent' for each component reference
- If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
- `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
- HOST_WIDE_INT offset;
- HOST_WIDE_INT size;
- tree base;
-
- /* Expression. It is context dependent so do not use it to create new
- expressions to access the original aggregate. See PR 42154 for a
- testcase. */
- tree expr;
- /* Type. */
- tree type;
-
- /* The statement this access belongs to. */
- gimple *stmt;
-
- /* Next group representative for this aggregate. */
- struct access *next_grp;
-
- /* Pointer to the group representative. Pointer to itself if the struct is
- the representative. */
- struct access *group_representative;
-
- /* After access tree has been constructed, this points to the parent of the
- current access, if there is one. NULL for roots. */
- struct access *parent;
-
- /* If this access has any children (in terms of the definition above), this
- points to the first one. */
- struct access *first_child;
-
- /* In intraprocedural SRA, pointer to the next sibling in the access tree as
- described above. */
- struct access *next_sibling;
-
- /* Pointers to the first and last element in the linked list of assign
- links for propagation from LHS to RHS. */
- struct assign_link *first_rhs_link, *last_rhs_link;
-
- /* Pointers to the first and last element in the linked list of assign
- links for propagation from LHS to RHS. */
- struct assign_link *first_lhs_link, *last_lhs_link;
-
- /* Pointer to the next access in the work queues. */
- struct access *next_rhs_queued, *next_lhs_queued;
-
- /* Replacement variable for this access "region." Never to be accessed
- directly, always only by the means of get_access_replacement() and only
- when grp_to_be_replaced flag is set. */
- tree replacement_decl;
-
- /* Is this access made in reverse storage order? */
- unsigned reverse : 1;
-
- /* Is this particular access write access? */
- unsigned write : 1;
-
- /* Is this access currently in the rhs work queue? */
- unsigned grp_rhs_queued : 1;
-
- /* Is this access currently in the lhs work queue? */
- unsigned grp_lhs_queued : 1;
-
- /* Does this group contain a write access? This flag is propagated down the
- access tree. */
- unsigned grp_write : 1;
-
- /* Does this group contain a read access? This flag is propagated down the
- access tree. */
- unsigned grp_read : 1;
-
- /* Does this group contain a read access that comes from an assignment
- statement? This flag is propagated down the access tree. */
- unsigned grp_assignment_read : 1;
-
- /* Does this group contain a write access that comes from an assignment
- statement? This flag is propagated down the access tree. */
- unsigned grp_assignment_write : 1;
-
- /* Does this group contain a read access through a scalar type? This flag is
- not propagated in the access tree in any direction. */
- unsigned grp_scalar_read : 1;
-
- /* Does this group contain a write access through a scalar type? This flag
- is not propagated in the access tree in any direction. */
- unsigned grp_scalar_write : 1;
-
- /* In a root of an access tree, true means that the entire tree should be
- totally scalarized - that all scalar leafs should be scalarized and
- non-root grp_total_scalarization accesses should be honored. Otherwise,
- non-root accesses with grp_total_scalarization should never get scalar
- replacements. */
- unsigned grp_total_scalarization : 1;
-
- /* Other passes of the analysis use this bit to make function
- analyze_access_subtree create scalar replacements for this group if
- possible. */
- unsigned grp_hint : 1;
-
- /* Is the subtree rooted in this access fully covered by scalar
- replacements? */
- unsigned grp_covered : 1;
-
- /* If set to true, this access and all below it in an access tree must not be
- scalarized. */
- unsigned grp_unscalarizable_region : 1;
-
- /* Whether data have been written to parts of the aggregate covered by this
- access which is not to be scalarized. This flag is propagated up in the
- access tree. */
- unsigned grp_unscalarized_data : 1;
-
- /* Set if all accesses in the group consist of the same chain of
- COMPONENT_REFs and ARRAY_REFs. */
- unsigned grp_same_access_path : 1;
-
- /* Does this access and/or group contain a write access through a
- BIT_FIELD_REF? */
- unsigned grp_partial_lhs : 1;
-
- /* Set when a scalar replacement should be created for this variable. */
- unsigned grp_to_be_replaced : 1;
-
- /* Set when we want a replacement for the sole purpose of having it in
- generated debug statements. */
- unsigned grp_to_be_debug_replaced : 1;
-
- /* Should TREE_NO_WARNING of a replacement be set? */
- unsigned grp_no_warning : 1;
-};
-
-typedef struct access *access_p;
-
-
-/* Alloc pool for allocating access structures. */
-static object_allocator<struct access> access_pool ("SRA accesses");
-
-/* A structure linking lhs and rhs accesses from an aggregate assignment. They
- are used to propagate subaccesses from rhs to lhs and vice versa as long as
- they don't conflict with what is already there. In the RHS->LHS direction,
- we also propagate grp_write flag to lazily mark that the access contains any
- meaningful data. */
-struct assign_link
-{
- struct access *lacc, *racc;
- struct assign_link *next_rhs, *next_lhs;
-};
-
-/* Alloc pool for allocating assign link structures. */
-static object_allocator<assign_link> assign_link_pool ("SRA links");
-
-/* Base (tree) -> Vector (vec<access_p> *) map. */
-static hash_map<tree, auto_vec<access_p> > *base_access_vec;
-
-/* Hash to limit creation of artificial accesses */
-static hash_map<tree, unsigned> *propagation_budget;
-
-/* Candidate hash table helpers. */
-
-struct uid_decl_hasher : nofree_ptr_hash <tree_node>
-{
- static inline hashval_t hash (const tree_node *);
- static inline bool equal (const tree_node *, const tree_node *);
-};
-
-/* Hash a tree in a uid_decl_map. */
-
-inline hashval_t
-uid_decl_hasher::hash (const tree_node *item)
-{
- return item->decl_minimal.uid;
-}
-
-/* Return true if the DECL_UID in both trees are equal. */
-
-inline bool
-uid_decl_hasher::equal (const tree_node *a, const tree_node *b)
-{
- return (a->decl_minimal.uid == b->decl_minimal.uid);
-}
-
-/* Set of candidates. */
-static bitmap candidate_bitmap;
-static hash_table<uid_decl_hasher> *candidates;
-
-/* For a candidate UID return the candidates decl. */
-
-static inline tree
-candidate (unsigned uid)
-{
- tree_node t;
- t.decl_minimal.uid = uid;
- return candidates->find_with_hash (&t, static_cast <hashval_t> (uid));
-}
-
-/* Bitmap of candidates which we should try to entirely scalarize away and
- those which cannot be (because they are and need be used as a whole). */
-static bitmap should_scalarize_away_bitmap, cannot_scalarize_away_bitmap;
-
-/* Bitmap of candidates in the constant pool, which cannot be scalarized
- because this would produce non-constant expressions (e.g. Ada). */
-static bitmap disqualified_constants;
-
-/* Obstack for creation of fancy names. */
-static struct obstack name_obstack;
-
-/* Head of a linked list of accesses that need to have its subaccesses
- propagated to their assignment counterparts. */
-static struct access *rhs_work_queue_head, *lhs_work_queue_head;
-
-/* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
- representative fields are dumped, otherwise those which only describe the
- individual access are. */
-
-static struct
-{
- /* Number of processed aggregates is readily available in
- analyze_all_variable_accesses and so is not stored here. */
-
- /* Number of created scalar replacements. */
- int replacements;
-
- /* Number of times sra_modify_expr or sra_modify_assign themselves changed an
- expression. */
- int exprs;
-
- /* Number of statements created by generate_subtree_copies. */
- int subtree_copies;
-
- /* Number of statements created by load_assign_lhs_subreplacements. */
- int subreplacements;
-
- /* Number of times sra_modify_assign has deleted a statement. */
- int deleted;
-
- /* Number of times sra_modify_assign has to deal with subaccesses of LHS and
- RHS reparately due to type conversions or nonexistent matching
- references. */
- int separate_lhs_rhs_handling;
-
- /* Number of parameters that were removed because they were unused. */
- int deleted_unused_parameters;
-
- /* Number of scalars passed as parameters by reference that have been
- converted to be passed by value. */
- int scalar_by_ref_to_by_val;
-
- /* Number of aggregate parameters that were replaced by one or more of their
- components. */
- int aggregate_params_reduced;
-
- /* Numbber of components created when splitting aggregate parameters. */
- int param_reductions_created;
-
- /* Number of deferred_init calls that are modified. */
- int deferred_init;
-
- /* Number of deferred_init calls that are created by
- generate_subtree_deferred_init. */
- int subtree_deferred_init;
-} sra_stats;
-
-static void
-dump_access (FILE *f, struct access *access, bool grp)
-{
- fprintf (f, "access { ");
- fprintf (f, "base = (%d)'", DECL_UID (access->base));
- print_generic_expr (f, access->base);
- fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
- fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
- fprintf (f, ", expr = ");
- print_generic_expr (f, access->expr);
- fprintf (f, ", type = ");
- print_generic_expr (f, access->type);
- fprintf (f, ", reverse = %d", access->reverse);
- if (grp)
- fprintf (f, ", grp_read = %d, grp_write = %d, grp_assignment_read = %d, "
- "grp_assignment_write = %d, grp_scalar_read = %d, "
- "grp_scalar_write = %d, grp_total_scalarization = %d, "
- "grp_hint = %d, grp_covered = %d, "
- "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
- "grp_same_access_path = %d, grp_partial_lhs = %d, "
- "grp_to_be_replaced = %d, grp_to_be_debug_replaced = %d}\n",
- access->grp_read, access->grp_write, access->grp_assignment_read,
- access->grp_assignment_write, access->grp_scalar_read,
- access->grp_scalar_write, access->grp_total_scalarization,
- access->grp_hint, access->grp_covered,
- access->grp_unscalarizable_region, access->grp_unscalarized_data,
- access->grp_same_access_path, access->grp_partial_lhs,
- access->grp_to_be_replaced, access->grp_to_be_debug_replaced);
- else
- fprintf (f, ", write = %d, grp_total_scalarization = %d, "
- "grp_partial_lhs = %d}\n",
- access->write, access->grp_total_scalarization,
- access->grp_partial_lhs);
-}
-
-/* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
-
-static void
-dump_access_tree_1 (FILE *f, struct access *access, int level)
-{
- do
- {
- int i;
-
- for (i = 0; i < level; i++)
- fputs ("* ", f);
-
- dump_access (f, access, true);
-
- if (access->first_child)
- dump_access_tree_1 (f, access->first_child, level + 1);
-
- access = access->next_sibling;
- }
- while (access);
-}
-
-/* Dump all access trees for a variable, given the pointer to the first root in
- ACCESS. */
-
-static void
-dump_access_tree (FILE *f, struct access *access)
-{
- for (; access; access = access->next_grp)
- dump_access_tree_1 (f, access, 0);
-}
-
-/* Return true iff ACC is non-NULL and has subaccesses. */
-
-static inline bool
-access_has_children_p (struct access *acc)
-{
- return acc && acc->first_child;
-}
-
-/* Return true iff ACC is (partly) covered by at least one replacement. */
-
-static bool
-access_has_replacements_p (struct access *acc)
-{
- struct access *child;
- if (acc->grp_to_be_replaced)
- return true;
- for (child = acc->first_child; child; child = child->next_sibling)
- if (access_has_replacements_p (child))
- return true;
- return false;
-}
-
-/* Return a vector of pointers to accesses for the variable given in BASE or
- NULL if there is none. */
-
-static vec<access_p> *
-get_base_access_vector (tree base)
-{
- return base_access_vec->get (base);
-}
-
-/* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
- in ACCESS. Return NULL if it cannot be found. */
-
-static struct access *
-find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
- HOST_WIDE_INT size)
-{
- while (access && (access->offset != offset || access->size != size))
- {
- struct access *child = access->first_child;
-
- while (child && (child->offset + child->size <= offset))
- child = child->next_sibling;
- access = child;
- }
-
- /* Total scalarization does not replace single field structures with their
- single field but rather creates an access for them underneath. Look for
- it. */
- if (access)
- while (access->first_child
- && access->first_child->offset == offset
- && access->first_child->size == size)
- access = access->first_child;
-
- return access;
-}
-
-/* Return the first group representative for DECL or NULL if none exists. */
-
-static struct access *
-get_first_repr_for_decl (tree base)
-{
- vec<access_p> *access_vec;
-
- access_vec = get_base_access_vector (base);
- if (!access_vec)
- return NULL;
-
- return (*access_vec)[0];
-}
-
-/* Find an access representative for the variable BASE and given OFFSET and
- SIZE. Requires that access trees have already been built. Return NULL if
- it cannot be found. */
-
-static struct access *
-get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
- HOST_WIDE_INT size)
-{
- struct access *access;
-
- access = get_first_repr_for_decl (base);
- while (access && (access->offset + access->size <= offset))
- access = access->next_grp;
- if (!access)
- return NULL;
-
- return find_access_in_subtree (access, offset, size);
-}
-
-/* Add LINK to the linked list of assign links of RACC. */
-
-static void
-add_link_to_rhs (struct access *racc, struct assign_link *link)
-{
- gcc_assert (link->racc == racc);
-
- if (!racc->first_rhs_link)
- {
- gcc_assert (!racc->last_rhs_link);
- racc->first_rhs_link = link;
- }
- else
- racc->last_rhs_link->next_rhs = link;
-
- racc->last_rhs_link = link;
- link->next_rhs = NULL;
-}
-
-/* Add LINK to the linked list of lhs assign links of LACC. */
-
-static void
-add_link_to_lhs (struct access *lacc, struct assign_link *link)
-{
- gcc_assert (link->lacc == lacc);
-
- if (!lacc->first_lhs_link)
- {
- gcc_assert (!lacc->last_lhs_link);
- lacc->first_lhs_link = link;
- }
- else
- lacc->last_lhs_link->next_lhs = link;
-
- lacc->last_lhs_link = link;
- link->next_lhs = NULL;
-}
-
-/* Move all link structures in their linked list in OLD_ACC to the linked list
- in NEW_ACC. */
-static void
-relink_to_new_repr (struct access *new_acc, struct access *old_acc)
-{
- if (old_acc->first_rhs_link)
- {
-
- if (new_acc->first_rhs_link)
- {
- gcc_assert (!new_acc->last_rhs_link->next_rhs);
- gcc_assert (!old_acc->last_rhs_link
- || !old_acc->last_rhs_link->next_rhs);
-
- new_acc->last_rhs_link->next_rhs = old_acc->first_rhs_link;
- new_acc->last_rhs_link = old_acc->last_rhs_link;
- }
- else
- {
- gcc_assert (!new_acc->last_rhs_link);
-
- new_acc->first_rhs_link = old_acc->first_rhs_link;
- new_acc->last_rhs_link = old_acc->last_rhs_link;
- }
- old_acc->first_rhs_link = old_acc->last_rhs_link = NULL;
- }
- else
- gcc_assert (!old_acc->last_rhs_link);
-
- if (old_acc->first_lhs_link)
- {
-
- if (new_acc->first_lhs_link)
- {
- gcc_assert (!new_acc->last_lhs_link->next_lhs);
- gcc_assert (!old_acc->last_lhs_link
- || !old_acc->last_lhs_link->next_lhs);
-
- new_acc->last_lhs_link->next_lhs = old_acc->first_lhs_link;
- new_acc->last_lhs_link = old_acc->last_lhs_link;
- }
- else
- {
- gcc_assert (!new_acc->last_lhs_link);
-
- new_acc->first_lhs_link = old_acc->first_lhs_link;
- new_acc->last_lhs_link = old_acc->last_lhs_link;
- }
- old_acc->first_lhs_link = old_acc->last_lhs_link = NULL;
- }
- else
- gcc_assert (!old_acc->last_lhs_link);
-
-}
-
-/* Add ACCESS to the work to queue for propagation of subaccesses from RHS to
- LHS (which is actually a stack). */
-
-static void
-add_access_to_rhs_work_queue (struct access *access)
-{
- if (access->first_rhs_link && !access->grp_rhs_queued)
- {
- gcc_assert (!access->next_rhs_queued);
- access->next_rhs_queued = rhs_work_queue_head;
- access->grp_rhs_queued = 1;
- rhs_work_queue_head = access;
- }
-}
-
-/* Add ACCESS to the work to queue for propagation of subaccesses from LHS to
- RHS (which is actually a stack). */
-
-static void
-add_access_to_lhs_work_queue (struct access *access)
-{
- if (access->first_lhs_link && !access->grp_lhs_queued)
- {
- gcc_assert (!access->next_lhs_queued);
- access->next_lhs_queued = lhs_work_queue_head;
- access->grp_lhs_queued = 1;
- lhs_work_queue_head = access;
- }
-}
-
-/* Pop an access from the work queue for propagating from RHS to LHS, and
- return it, assuming there is one. */
-
-static struct access *
-pop_access_from_rhs_work_queue (void)
-{
- struct access *access = rhs_work_queue_head;
-
- rhs_work_queue_head = access->next_rhs_queued;
- access->next_rhs_queued = NULL;
- access->grp_rhs_queued = 0;
- return access;
-}
-
-/* Pop an access from the work queue for propagating from LHS to RHS, and
- return it, assuming there is one. */
-
-static struct access *
-pop_access_from_lhs_work_queue (void)
-{
- struct access *access = lhs_work_queue_head;
-
- lhs_work_queue_head = access->next_lhs_queued;
- access->next_lhs_queued = NULL;
- access->grp_lhs_queued = 0;
- return access;
-}
-
-/* Allocate necessary structures. */
-
-static void
-sra_initialize (void)
-{
- candidate_bitmap = BITMAP_ALLOC (NULL);
- candidates = new hash_table<uid_decl_hasher>
- (vec_safe_length (cfun->local_decls) / 2);
- should_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
- cannot_scalarize_away_bitmap = BITMAP_ALLOC (NULL);
- disqualified_constants = BITMAP_ALLOC (NULL);
- gcc_obstack_init (&name_obstack);
- base_access_vec = new hash_map<tree, auto_vec<access_p> >;
- memset (&sra_stats, 0, sizeof (sra_stats));
-}
-
-/* Deallocate all general structures. */
-
-static void
-sra_deinitialize (void)
-{
- BITMAP_FREE (candidate_bitmap);
- delete candidates;
- candidates = NULL;
- BITMAP_FREE (should_scalarize_away_bitmap);
- BITMAP_FREE (cannot_scalarize_away_bitmap);
- BITMAP_FREE (disqualified_constants);
- access_pool.release ();
- assign_link_pool.release ();
- obstack_free (&name_obstack, NULL);
-
- delete base_access_vec;
-}
-
-/* Return true if DECL is a VAR_DECL in the constant pool, false otherwise. */
-
-static bool constant_decl_p (tree decl)
-{
- return VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl);
-}
-
-/* Remove DECL from candidates for SRA and write REASON to the dump file if
- there is one. */
-
-static void
-disqualify_candidate (tree decl, const char *reason)
-{
- if (bitmap_clear_bit (candidate_bitmap, DECL_UID (decl)))
- candidates->remove_elt_with_hash (decl, DECL_UID (decl));
- if (constant_decl_p (decl))
- bitmap_set_bit (disqualified_constants, DECL_UID (decl));
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "! Disqualifying ");
- print_generic_expr (dump_file, decl);
- fprintf (dump_file, " - %s\n", reason);
- }
-}
-
-/* Return true iff the type contains a field or an element which does not allow
- scalarization. Use VISITED_TYPES to avoid re-checking already checked
- (sub-)types. */
-
-static bool
-type_internals_preclude_sra_p_1 (tree type, const char **msg,
- hash_set<tree> *visited_types)
-{
- tree fld;
- tree et;
-
- if (visited_types->contains (type))
- return false;
- visited_types->add (type);
-
- switch (TREE_CODE (type))
- {
- case RECORD_TYPE:
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
- if (TREE_CODE (fld) == FIELD_DECL)
- {
- if (TREE_CODE (fld) == FUNCTION_DECL)
- continue;
- tree ft = TREE_TYPE (fld);
-
- if (TREE_THIS_VOLATILE (fld))
- {
- *msg = "volatile structure field";
- return true;
- }
- if (!DECL_FIELD_OFFSET (fld))
- {
- *msg = "no structure field offset";
- return true;
- }
- if (!DECL_SIZE (fld))
- {
- *msg = "zero structure field size";
- return true;
- }
- if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (fld)))
- {
- *msg = "structure field offset not fixed";
- return true;
- }
- if (!tree_fits_uhwi_p (DECL_SIZE (fld)))
- {
- *msg = "structure field size not fixed";
- return true;
- }
- if (!tree_fits_shwi_p (bit_position (fld)))
- {
- *msg = "structure field size too big";
- return true;
- }
- if (AGGREGATE_TYPE_P (ft)
- && int_bit_position (fld) % BITS_PER_UNIT != 0)
- {
- *msg = "structure field is bit field";
- return true;
- }
-
- if (AGGREGATE_TYPE_P (ft)
- && type_internals_preclude_sra_p_1 (ft, msg, visited_types))
- return true;
- }
-
- return false;
-
- case ARRAY_TYPE:
- et = TREE_TYPE (type);
-
- if (TYPE_VOLATILE (et))
- {
- *msg = "element type is volatile";
- return true;
- }
-
- if (AGGREGATE_TYPE_P (et)
- && type_internals_preclude_sra_p_1 (et, msg, visited_types))
- return true;
-
- return false;
-
- default:
- return false;
- }
-}
-
-/* Return true iff the type contains a field or an element which does not allow
- scalarization. */
-
-bool
-type_internals_preclude_sra_p (tree type, const char **msg)
-{
- hash_set<tree> visited_types;
- return type_internals_preclude_sra_p_1 (type, msg, &visited_types);
-}
-
-
-/* Allocate an access structure for BASE, OFFSET and SIZE, clear it, fill in
- the three fields. Also add it to the vector of accesses corresponding to
- the base. Finally, return the new access. */
-
-static struct access *
-create_access_1 (tree base, HOST_WIDE_INT offset, HOST_WIDE_INT size)
-{
- struct access *access = access_pool.allocate ();
-
- memset (access, 0, sizeof (struct access));
- access->base = base;
- access->offset = offset;
- access->size = size;
-
- base_access_vec->get_or_insert (base).safe_push (access);
-
- return access;
-}
-
-static bool maybe_add_sra_candidate (tree);
-
-/* Create and insert access for EXPR. Return created access, or NULL if it is
- not possible. Also scan for uses of constant pool as we go along and add
- to candidates. */
-
-static struct access *
-create_access (tree expr, gimple *stmt, bool write)
-{
- struct access *access;
- poly_int64 poffset, psize, pmax_size;
- tree base = expr;
- bool reverse, unscalarizable_region = false;
-
- base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
- &reverse);
-
- /* For constant-pool entries, check we can substitute the constant value. */
- if (constant_decl_p (base))
- {
- gcc_assert (!bitmap_bit_p (disqualified_constants, DECL_UID (base)));
- if (expr != base
- && !is_gimple_reg_type (TREE_TYPE (expr))
- && dump_file && (dump_flags & TDF_DETAILS))
- {
- /* This occurs in Ada with accesses to ARRAY_RANGE_REFs,
- and elements of multidimensional arrays (which are
- multi-element arrays in their own right). */
- fprintf (dump_file, "Allowing non-reg-type load of part"
- " of constant-pool entry: ");
- print_generic_expr (dump_file, expr);
- }
- maybe_add_sra_candidate (base);
- }
-
- if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
- return NULL;
-
- if (write && TREE_READONLY (base))
- {
- disqualify_candidate (base, "Encountered a store to a read-only decl.");
- return NULL;
- }
-
- HOST_WIDE_INT offset, size, max_size;
- if (!poffset.is_constant (&offset)
- || !psize.is_constant (&size)
- || !pmax_size.is_constant (&max_size))
- {
- disqualify_candidate (base, "Encountered a polynomial-sized access.");
- return NULL;
- }
-
- if (size != max_size)
- {
- size = max_size;
- unscalarizable_region = true;
- }
- if (size == 0)
- return NULL;
- if (offset < 0)
- {
- disqualify_candidate (base, "Encountered a negative offset access.");
- return NULL;
- }
- if (size < 0)
- {
- disqualify_candidate (base, "Encountered an unconstrained access.");
- return NULL;
- }
- if (offset + size > tree_to_shwi (DECL_SIZE (base)))
- {
- disqualify_candidate (base, "Encountered an access beyond the base.");
- return NULL;
- }
-
- access = create_access_1 (base, offset, size);
- access->expr = expr;
- access->type = TREE_TYPE (expr);
- access->write = write;
- access->grp_unscalarizable_region = unscalarizable_region;
- access->stmt = stmt;
- access->reverse = reverse;
-
- return access;
-}
-
-
-/* Return true iff TYPE is scalarizable - i.e. a RECORD_TYPE or fixed-length
- ARRAY_TYPE with fields that are either of gimple register types (excluding
- bit-fields) or (recursively) scalarizable types. CONST_DECL must be true if
- we are considering a decl from constant pool. If it is false, char arrays
- will be refused. */
-
-static bool
-scalarizable_type_p (tree type, bool const_decl)
-{
- if (is_gimple_reg_type (type))
- return true;
- if (type_contains_placeholder_p (type))
- return false;
-
- bool have_predecessor_field = false;
- HOST_WIDE_INT prev_pos = 0;
-
- switch (TREE_CODE (type))
- {
- case RECORD_TYPE:
- for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
- if (TREE_CODE (fld) == FIELD_DECL)
- {
- tree ft = TREE_TYPE (fld);
-
- if (zerop (DECL_SIZE (fld)))
- continue;
-
- HOST_WIDE_INT pos = int_bit_position (fld);
- if (have_predecessor_field
- && pos <= prev_pos)
- return false;
-
- have_predecessor_field = true;
- prev_pos = pos;
-
- if (DECL_BIT_FIELD (fld))
- return false;
-
- if (!scalarizable_type_p (ft, const_decl))
- return false;
- }
-
- return true;
-
- case ARRAY_TYPE:
- {
- HOST_WIDE_INT min_elem_size;
- if (const_decl)
- min_elem_size = 0;
- else
- min_elem_size = BITS_PER_UNIT;
-
- if (TYPE_DOMAIN (type) == NULL_TREE
- || !tree_fits_shwi_p (TYPE_SIZE (type))
- || !tree_fits_shwi_p (TYPE_SIZE (TREE_TYPE (type)))
- || (tree_to_shwi (TYPE_SIZE (TREE_TYPE (type))) <= min_elem_size)
- || !tree_fits_shwi_p (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
- return false;
- if (tree_to_shwi (TYPE_SIZE (type)) == 0
- && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)
- /* Zero-element array, should not prevent scalarization. */
- ;
- else if ((tree_to_shwi (TYPE_SIZE (type)) <= 0)
- || !tree_fits_shwi_p (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
- /* Variable-length array, do not allow scalarization. */
- return false;
-
- tree elem = TREE_TYPE (type);
- if (!scalarizable_type_p (elem, const_decl))
- return false;
- return true;
- }
- default:
- return false;
- }
-}
-
-/* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
-
-static inline bool
-contains_view_convert_expr_p (const_tree ref)
-{
- while (handled_component_p (ref))
- {
- if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
- return true;
- ref = TREE_OPERAND (ref, 0);
- }
-
- return false;
-}
-
-/* Return true if REF contains a VIEW_CONVERT_EXPR or a COMPONENT_REF with a
- bit-field field declaration. If TYPE_CHANGING_P is non-NULL, set the bool
- it points to will be set if REF contains any of the above or a MEM_REF
- expression that effectively performs type conversion. */
-
-static bool
-contains_vce_or_bfcref_p (const_tree ref, bool *type_changing_p = NULL)
-{
- while (handled_component_p (ref))
- {
- if (TREE_CODE (ref) == VIEW_CONVERT_EXPR
- || (TREE_CODE (ref) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (ref, 1))))
- {
- if (type_changing_p)
- *type_changing_p = true;
- return true;
- }
- ref = TREE_OPERAND (ref, 0);
- }
-
- if (!type_changing_p
- || TREE_CODE (ref) != MEM_REF
- || TREE_CODE (TREE_OPERAND (ref, 0)) != ADDR_EXPR)
- return false;
-
- tree mem = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
- if (TYPE_MAIN_VARIANT (TREE_TYPE (ref))
- != TYPE_MAIN_VARIANT (TREE_TYPE (mem)))
- *type_changing_p = true;
-
- return false;
-}
-
-/* Search the given tree for a declaration by skipping handled components and
- exclude it from the candidates. */
-
-static void
-disqualify_base_of_expr (tree t, const char *reason)
-{
- t = get_base_address (t);
- if (t && DECL_P (t))
- disqualify_candidate (t, reason);
-}
-
-/* Scan expression EXPR and create access structures for all accesses to
- candidates for scalarization. Return the created access or NULL if none is
- created. */
-
-static struct access *
-build_access_from_expr_1 (tree expr, gimple *stmt, bool write)
-{
- struct access *ret = NULL;
- bool partial_ref;
-
- if (TREE_CODE (expr) == BIT_FIELD_REF
- || TREE_CODE (expr) == IMAGPART_EXPR
- || TREE_CODE (expr) == REALPART_EXPR)
- {
- expr = TREE_OPERAND (expr, 0);
- partial_ref = true;
- }
- else
- partial_ref = false;
-
- if (storage_order_barrier_p (expr))
- {
- disqualify_base_of_expr (expr, "storage order barrier.");
- return NULL;
- }
-
- /* We need to dive through V_C_Es in order to get the size of its parameter
- and not the result type. Ada produces such statements. We are also
- capable of handling the topmost V_C_E but not any of those buried in other
- handled components. */
- if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
- expr = TREE_OPERAND (expr, 0);
-
- if (contains_view_convert_expr_p (expr))
- {
- disqualify_base_of_expr (expr, "V_C_E under a different handled "
- "component.");
- return NULL;
- }
- if (TREE_THIS_VOLATILE (expr))
- {
- disqualify_base_of_expr (expr, "part of a volatile reference.");
- return NULL;
- }
-
- switch (TREE_CODE (expr))
- {
- case MEM_REF:
- if (TREE_CODE (TREE_OPERAND (expr, 0)) != ADDR_EXPR)
- return NULL;
- /* fall through */
- case VAR_DECL:
- case PARM_DECL:
- case RESULT_DECL:
- case COMPONENT_REF:
- case ARRAY_REF:
- case ARRAY_RANGE_REF:
- ret = create_access (expr, stmt, write);
- break;
-
- default:
- break;
- }
-
- if (write && partial_ref && ret)
- ret->grp_partial_lhs = 1;
-
- return ret;
-}
-
-/* Scan expression EXPR and create access structures for all accesses to
- candidates for scalarization. Return true if any access has been inserted.
- STMT must be the statement from which the expression is taken, WRITE must be
- true if the expression is a store and false otherwise. */
-
-static bool
-build_access_from_expr (tree expr, gimple *stmt, bool write)
-{
- struct access *access;
-
- access = build_access_from_expr_1 (expr, stmt, write);
- if (access)
- {
- /* This means the aggregate is accesses as a whole in a way other than an
- assign statement and thus cannot be removed even if we had a scalar
- replacement for everything. */
- if (cannot_scalarize_away_bitmap)
- bitmap_set_bit (cannot_scalarize_away_bitmap, DECL_UID (access->base));
- return true;
- }
- return false;
-}
-
-/* Return the single non-EH successor edge of BB or NULL if there is none or
- more than one. */
-
-static edge
-single_non_eh_succ (basic_block bb)
-{
- edge e, res = NULL;
- edge_iterator ei;
-
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (!(e->flags & EDGE_EH))
- {
- if (res)
- return NULL;
- res = e;
- }
-
- return res;
-}
-
-/* Disqualify LHS and RHS for scalarization if STMT has to terminate its BB and
- there is no alternative spot where to put statements SRA might need to
- generate after it. The spot we are looking for is an edge leading to a
- single non-EH successor, if it exists and is indeed single. RHS may be
- NULL, in that case ignore it. */
-
-static bool
-disqualify_if_bad_bb_terminating_stmt (gimple *stmt, tree lhs, tree rhs)
-{
- if (stmt_ends_bb_p (stmt))
- {
- if (single_non_eh_succ (gimple_bb (stmt)))
- return false;
-
- disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
- if (rhs)
- disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
- return true;
- }
- return false;
-}
-
-/* Return true if the nature of BASE is such that it contains data even if
- there is no write to it in the function. */
-
-static bool
-comes_initialized_p (tree base)
-{
- return TREE_CODE (base) == PARM_DECL || constant_decl_p (base);
-}
-
-/* Scan expressions occurring in STMT, create access structures for all accesses
- to candidates for scalarization and remove those candidates which occur in
- statements or expressions that prevent them from being split apart. Return
- true if any access has been inserted. */
-
-static bool
-build_accesses_from_assign (gimple *stmt)
-{
- tree lhs, rhs;
- struct access *lacc, *racc;
-
- if (!gimple_assign_single_p (stmt)
- /* Scope clobbers don't influence scalarization. */
- || gimple_clobber_p (stmt))
- return false;
-
- lhs = gimple_assign_lhs (stmt);
- rhs = gimple_assign_rhs1 (stmt);
-
- if (disqualify_if_bad_bb_terminating_stmt (stmt, lhs, rhs))
- return false;
-
- racc = build_access_from_expr_1 (rhs, stmt, false);
- lacc = build_access_from_expr_1 (lhs, stmt, true);
-
- if (lacc)
- {
- lacc->grp_assignment_write = 1;
- if (storage_order_barrier_p (rhs))
- lacc->grp_unscalarizable_region = 1;
-
- if (should_scalarize_away_bitmap && !is_gimple_reg_type (lacc->type))
- {
- bool type_changing_p = false;
- contains_vce_or_bfcref_p (lhs, &type_changing_p);
- if (type_changing_p)
- bitmap_set_bit (cannot_scalarize_away_bitmap,
- DECL_UID (lacc->base));
- }
- }
-
- if (racc)
- {
- racc->grp_assignment_read = 1;
- if (should_scalarize_away_bitmap && !is_gimple_reg_type (racc->type))
- {
- bool type_changing_p = false;
- contains_vce_or_bfcref_p (rhs, &type_changing_p);
-
- if (type_changing_p || gimple_has_volatile_ops (stmt))
- bitmap_set_bit (cannot_scalarize_away_bitmap,
- DECL_UID (racc->base));
- else
- bitmap_set_bit (should_scalarize_away_bitmap,
- DECL_UID (racc->base));
- }
- if (storage_order_barrier_p (lhs))
- racc->grp_unscalarizable_region = 1;
- }
-
- if (lacc && racc
- && (sra_mode == SRA_MODE_EARLY_INTRA || sra_mode == SRA_MODE_INTRA)
- && !lacc->grp_unscalarizable_region
- && !racc->grp_unscalarizable_region
- && AGGREGATE_TYPE_P (TREE_TYPE (lhs))
- && lacc->size == racc->size
- && useless_type_conversion_p (lacc->type, racc->type))
- {
- struct assign_link *link;
-
- link = assign_link_pool.allocate ();
- memset (link, 0, sizeof (struct assign_link));
-
- link->lacc = lacc;
- link->racc = racc;
- add_link_to_rhs (racc, link);
- add_link_to_lhs (lacc, link);
- add_access_to_rhs_work_queue (racc);
- add_access_to_lhs_work_queue (lacc);
-
- /* Let's delay marking the areas as written until propagation of accesses
- across link, unless the nature of rhs tells us that its data comes
- from elsewhere. */
- if (!comes_initialized_p (racc->base))
- lacc->write = false;
- }
-
- return lacc || racc;
-}
-
-/* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
- GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
-
-static bool
-asm_visit_addr (gimple *, tree op, tree, void *)
-{
- op = get_base_address (op);
- if (op
- && DECL_P (op))
- disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
-
- return false;
-}
-
-/* Scan function and look for interesting expressions and create access
- structures for them. Return true iff any access is created. */
-
-static bool
-scan_function (void)
-{
- basic_block bb;
- bool ret = false;
-
- FOR_EACH_BB_FN (bb, cfun)
- {
- gimple_stmt_iterator gsi;
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- tree t;
- unsigned i;
-
- switch (gimple_code (stmt))
- {
- case GIMPLE_RETURN:
- t = gimple_return_retval (as_a <greturn *> (stmt));
- if (t != NULL_TREE)
- ret |= build_access_from_expr (t, stmt, false);
- break;
-
- case GIMPLE_ASSIGN:
- ret |= build_accesses_from_assign (stmt);
- break;
-
- case GIMPLE_CALL:
- for (i = 0; i < gimple_call_num_args (stmt); i++)
- ret |= build_access_from_expr (gimple_call_arg (stmt, i),
- stmt, false);
-
- t = gimple_call_lhs (stmt);
- if (t && !disqualify_if_bad_bb_terminating_stmt (stmt, t, NULL))
- {
- /* If the STMT is a call to DEFERRED_INIT, avoid setting
- cannot_scalarize_away_bitmap. */
- if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
- ret |= !!build_access_from_expr_1 (t, stmt, true);
- else
- ret |= build_access_from_expr (t, stmt, true);
- }
- break;
-
- case GIMPLE_ASM:
- {
- gasm *asm_stmt = as_a <gasm *> (stmt);
- walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL,
- asm_visit_addr);
- for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
- {
- t = TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
- ret |= build_access_from_expr (t, asm_stmt, false);
- }
- for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
- {
- t = TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
- ret |= build_access_from_expr (t, asm_stmt, true);
- }
- }
- break;
-
- default:
- break;
- }
- }
- }
-
- return ret;
-}
-
-/* Helper of QSORT function. There are pointers to accesses in the array. An
- access is considered smaller than another if it has smaller offset or if the
- offsets are the same but is size is bigger. */
-
-static int
-compare_access_positions (const void *a, const void *b)
-{
- const access_p *fp1 = (const access_p *) a;
- const access_p *fp2 = (const access_p *) b;
- const access_p f1 = *fp1;
- const access_p f2 = *fp2;
-
- if (f1->offset != f2->offset)
- return f1->offset < f2->offset ? -1 : 1;
-
- if (f1->size == f2->size)
- {
- if (f1->type == f2->type)
- return 0;
- /* Put any non-aggregate type before any aggregate type. */
- else if (!is_gimple_reg_type (f1->type)
- && is_gimple_reg_type (f2->type))
- return 1;
- else if (is_gimple_reg_type (f1->type)
- && !is_gimple_reg_type (f2->type))
- return -1;
- /* Put any complex or vector type before any other scalar type. */
- else if (TREE_CODE (f1->type) != COMPLEX_TYPE
- && TREE_CODE (f1->type) != VECTOR_TYPE
- && (TREE_CODE (f2->type) == COMPLEX_TYPE
- || TREE_CODE (f2->type) == VECTOR_TYPE))
- return 1;
- else if ((TREE_CODE (f1->type) == COMPLEX_TYPE
- || TREE_CODE (f1->type) == VECTOR_TYPE)
- && TREE_CODE (f2->type) != COMPLEX_TYPE
- && TREE_CODE (f2->type) != VECTOR_TYPE)
- return -1;
- /* Put any integral type before any non-integral type. When splicing, we
- make sure that those with insufficient precision and occupying the
- same space are not scalarized. */
- else if (INTEGRAL_TYPE_P (f1->type)
- && !INTEGRAL_TYPE_P (f2->type))
- return -1;
- else if (!INTEGRAL_TYPE_P (f1->type)
- && INTEGRAL_TYPE_P (f2->type))
- return 1;
- /* Put the integral type with the bigger precision first. */
- else if (INTEGRAL_TYPE_P (f1->type)
- && INTEGRAL_TYPE_P (f2->type)
- && (TYPE_PRECISION (f2->type) != TYPE_PRECISION (f1->type)))
- return TYPE_PRECISION (f2->type) - TYPE_PRECISION (f1->type);
- /* Stabilize the sort. */
- return TYPE_UID (f1->type) - TYPE_UID (f2->type);
- }
-
- /* We want the bigger accesses first, thus the opposite operator in the next
- line: */
- return f1->size > f2->size ? -1 : 1;
-}
-
-
-/* Append a name of the declaration to the name obstack. A helper function for
- make_fancy_name. */
-
-static void
-make_fancy_decl_name (tree decl)
-{
- char buffer[32];
-
- tree name = DECL_NAME (decl);
- if (name)
- obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
- IDENTIFIER_LENGTH (name));
- else
- {
- sprintf (buffer, "D%u", DECL_UID (decl));
- obstack_grow (&name_obstack, buffer, strlen (buffer));
- }
-}
-
-/* Helper for make_fancy_name. */
-
-static void
-make_fancy_name_1 (tree expr)
-{
- char buffer[32];
- tree index;
-
- if (DECL_P (expr))
- {
- make_fancy_decl_name (expr);
- return;
- }
-
- switch (TREE_CODE (expr))
- {
- case COMPONENT_REF:
- make_fancy_name_1 (TREE_OPERAND (expr, 0));
- obstack_1grow (&name_obstack, '$');
- make_fancy_decl_name (TREE_OPERAND (expr, 1));
- break;
-
- case ARRAY_REF:
- make_fancy_name_1 (TREE_OPERAND (expr, 0));
- obstack_1grow (&name_obstack, '$');
- /* Arrays with only one element may not have a constant as their
- index. */
- index = TREE_OPERAND (expr, 1);
- if (TREE_CODE (index) != INTEGER_CST)
- break;
- sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
- obstack_grow (&name_obstack, buffer, strlen (buffer));
- break;
-
- case ADDR_EXPR:
- make_fancy_name_1 (TREE_OPERAND (expr, 0));
- break;
-
- case MEM_REF:
- make_fancy_name_1 (TREE_OPERAND (expr, 0));
- if (!integer_zerop (TREE_OPERAND (expr, 1)))
- {
- obstack_1grow (&name_obstack, '$');
- sprintf (buffer, HOST_WIDE_INT_PRINT_DEC,
- TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)));
- obstack_grow (&name_obstack, buffer, strlen (buffer));
- }
- break;
-
- case BIT_FIELD_REF:
- case REALPART_EXPR:
- case IMAGPART_EXPR:
- gcc_unreachable (); /* we treat these as scalars. */
- break;
- default:
- break;
- }
-}
-
-/* Create a human readable name for replacement variable of ACCESS. */
-
-static char *
-make_fancy_name (tree expr)
-{
- make_fancy_name_1 (expr);
- obstack_1grow (&name_obstack, '\0');
- return XOBFINISH (&name_obstack, char *);
-}
-
-/* Construct a MEM_REF that would reference a part of aggregate BASE of type
- EXP_TYPE at the given OFFSET and with storage order REVERSE. If BASE is
- something for which get_addr_base_and_unit_offset returns NULL, gsi must
- be non-NULL and is used to insert new statements either before or below
- the current one as specified by INSERT_AFTER. This function is not capable
- of handling bitfields. */
-
-tree
-build_ref_for_offset (location_t loc, tree base, poly_int64 offset,
- bool reverse, tree exp_type, gimple_stmt_iterator *gsi,
- bool insert_after)
-{
- tree prev_base = base;
- tree off;
- tree mem_ref;
- poly_int64 base_offset;
- unsigned HOST_WIDE_INT misalign;
- unsigned int align;
-
- /* Preserve address-space information. */
- addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (base));
- if (as != TYPE_ADDR_SPACE (exp_type))
- exp_type = build_qualified_type (exp_type,
- TYPE_QUALS (exp_type)
- | ENCODE_QUAL_ADDR_SPACE (as));
-
- poly_int64 byte_offset = exact_div (offset, BITS_PER_UNIT);
- get_object_alignment_1 (base, &align, &misalign);
- base = get_addr_base_and_unit_offset (base, &base_offset);
-
- /* get_addr_base_and_unit_offset returns NULL for references with a variable
- offset such as array[var_index]. */
- if (!base)
- {
- gassign *stmt;
- tree tmp, addr;
-
- gcc_checking_assert (gsi);
- tmp = make_ssa_name (build_pointer_type (TREE_TYPE (prev_base)));
- addr = build_fold_addr_expr (unshare_expr (prev_base));
- STRIP_USELESS_TYPE_CONVERSION (addr);
- stmt = gimple_build_assign (tmp, addr);
- gimple_set_location (stmt, loc);
- if (insert_after)
- gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
- else
- gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
-
- off = build_int_cst (reference_alias_ptr_type (prev_base), byte_offset);
- base = tmp;
- }
- else if (TREE_CODE (base) == MEM_REF)
- {
- off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
- base_offset + byte_offset);
- off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
- base = unshare_expr (TREE_OPERAND (base, 0));
- }
- else
- {
- off = build_int_cst (reference_alias_ptr_type (prev_base),
- base_offset + byte_offset);
- base = build_fold_addr_expr (unshare_expr (base));
- }
-
- unsigned int align_bound = known_alignment (misalign + offset);
- if (align_bound != 0)
- align = MIN (align, align_bound);
- if (align != TYPE_ALIGN (exp_type))
- exp_type = build_aligned_type (exp_type, align);
-
- mem_ref = fold_build2_loc (loc, MEM_REF, exp_type, base, off);
- REF_REVERSE_STORAGE_ORDER (mem_ref) = reverse;
- if (TREE_THIS_VOLATILE (prev_base))
- TREE_THIS_VOLATILE (mem_ref) = 1;
- if (TREE_SIDE_EFFECTS (prev_base))
- TREE_SIDE_EFFECTS (mem_ref) = 1;
- return mem_ref;
-}
-
-/* Construct and return a memory reference that is equal to a portion of
- MODEL->expr but is based on BASE. If this cannot be done, return NULL. */
-
-static tree
-build_reconstructed_reference (location_t, tree base, struct access *model)
-{
- tree expr = model->expr, prev_expr = NULL;
- while (!types_compatible_p (TREE_TYPE (expr), TREE_TYPE (base)))
- {
- if (!handled_component_p (expr))
- return NULL_TREE;
- prev_expr = expr;
- expr = TREE_OPERAND (expr, 0);
- }
-
- /* Guard against broken VIEW_CONVERT_EXPRs... */
- if (!prev_expr)
- return NULL_TREE;
-
- TREE_OPERAND (prev_expr, 0) = base;
- tree ref = unshare_expr (model->expr);
- TREE_OPERAND (prev_expr, 0) = expr;
- return ref;
-}
-
-/* Construct a memory reference to a part of an aggregate BASE at the given
- OFFSET and of the same type as MODEL. In case this is a reference to a
- bit-field, the function will replicate the last component_ref of model's
- expr to access it. GSI and INSERT_AFTER have the same meaning as in
- build_ref_for_offset. */
-
-static tree
-build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
- struct access *model, gimple_stmt_iterator *gsi,
- bool insert_after)
-{
- gcc_assert (offset >= 0);
- if (TREE_CODE (model->expr) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
- {
- /* This access represents a bit-field. */
- tree t, exp_type, fld = TREE_OPERAND (model->expr, 1);
-
- offset -= int_bit_position (fld);
- exp_type = TREE_TYPE (TREE_OPERAND (model->expr, 0));
- t = build_ref_for_offset (loc, base, offset, model->reverse, exp_type,
- gsi, insert_after);
- /* The flag will be set on the record type. */
- REF_REVERSE_STORAGE_ORDER (t) = 0;
- return fold_build3_loc (loc, COMPONENT_REF, TREE_TYPE (fld), t, fld,
- NULL_TREE);
- }
- else
- {
- tree res;
- if (model->grp_same_access_path
- && !TREE_THIS_VOLATILE (base)
- && (TYPE_ADDR_SPACE (TREE_TYPE (base))
- == TYPE_ADDR_SPACE (TREE_TYPE (model->expr)))
- && offset <= model->offset
- /* build_reconstructed_reference can still fail if we have already
- massaged BASE because of another type incompatibility. */
- && (res = build_reconstructed_reference (loc, base, model)))
- return res;
- else
- return build_ref_for_offset (loc, base, offset, model->reverse,
- model->type, gsi, insert_after);
- }
-}
-
-/* Attempt to build a memory reference that we could but into a gimple
- debug_bind statement. Similar to build_ref_for_model but punts if it has to
- create statements and return s NULL instead. This function also ignores
- alignment issues and so its results should never end up in non-debug
- statements. */
-
-static tree
-build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
- struct access *model)
-{
- poly_int64 base_offset;
- tree off;
-
- if (TREE_CODE (model->expr) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
- return NULL_TREE;
-
- base = get_addr_base_and_unit_offset (base, &base_offset);
- if (!base)
- return NULL_TREE;
- if (TREE_CODE (base) == MEM_REF)
- {
- off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
- base_offset + offset / BITS_PER_UNIT);
- off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
- base = unshare_expr (TREE_OPERAND (base, 0));
- }
- else
- {
- off = build_int_cst (reference_alias_ptr_type (base),
- base_offset + offset / BITS_PER_UNIT);
- base = build_fold_addr_expr (unshare_expr (base));
- }
-
- return fold_build2_loc (loc, MEM_REF, model->type, base, off);
-}
-
-/* Construct a memory reference consisting of component_refs and array_refs to
- a part of an aggregate *RES (which is of type TYPE). The requested part
- should have type EXP_TYPE at be the given OFFSET. This function might not
- succeed, it returns true when it does and only then *RES points to something
- meaningful. This function should be used only to build expressions that we
- might need to present to user (e.g. in warnings). In all other situations,
- build_ref_for_model or build_ref_for_offset should be used instead. */
-
-static bool
-build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
- tree exp_type)
-{
- while (1)
- {
- tree fld;
- tree tr_size, index, minidx;
- HOST_WIDE_INT el_size;
-
- if (offset == 0 && exp_type
- && types_compatible_p (exp_type, type))
- return true;
-
- switch (TREE_CODE (type))
- {
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- case RECORD_TYPE:
- for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
- {
- HOST_WIDE_INT pos, size;
- tree tr_pos, expr, *expr_ptr;
-
- if (TREE_CODE (fld) != FIELD_DECL)
- continue;
-
- tr_pos = bit_position (fld);
- if (!tr_pos || !tree_fits_uhwi_p (tr_pos))
- continue;
- pos = tree_to_uhwi (tr_pos);
- gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
- tr_size = DECL_SIZE (fld);
- if (!tr_size || !tree_fits_uhwi_p (tr_size))
- continue;
- size = tree_to_uhwi (tr_size);
- if (size == 0)
- {
- if (pos != offset)
- continue;
- }
- else if (pos > offset || (pos + size) <= offset)
- continue;
-
- expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
- NULL_TREE);
- expr_ptr = &expr;
- if (build_user_friendly_ref_for_offset (expr_ptr, TREE_TYPE (fld),
- offset - pos, exp_type))
- {
- *res = expr;
- return true;
- }
- }
- return false;
-
- case ARRAY_TYPE:
- tr_size = TYPE_SIZE (TREE_TYPE (type));
- if (!tr_size || !tree_fits_uhwi_p (tr_size))
- return false;
- el_size = tree_to_uhwi (tr_size);
-
- minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
- if (TREE_CODE (minidx) != INTEGER_CST || el_size == 0)
- return false;
- index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
- if (!integer_zerop (minidx))
- index = int_const_binop (PLUS_EXPR, index, minidx);
- *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
- NULL_TREE, NULL_TREE);
- offset = offset % el_size;
- type = TREE_TYPE (type);
- break;
-
- default:
- if (offset != 0)
- return false;
-
- if (exp_type)
- return false;
- else
- return true;
- }
- }
-}
-
-/* Print message to dump file why a variable was rejected. */
-
-static void
-reject (tree var, const char *msg)
-{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Rejected (%d): %s: ", DECL_UID (var), msg);
- print_generic_expr (dump_file, var);
- fprintf (dump_file, "\n");
- }
-}
-
-/* Return true if VAR is a candidate for SRA. */
-
-static bool
-maybe_add_sra_candidate (tree var)
-{
- tree type = TREE_TYPE (var);
- const char *msg;
- tree_node **slot;
-
- if (!AGGREGATE_TYPE_P (type))
- {
- reject (var, "not aggregate");
- return false;
- }
- /* Allow constant-pool entries that "need to live in memory". */
- if (needs_to_live_in_memory (var) && !constant_decl_p (var))
- {
- reject (var, "needs to live in memory");
- return false;
- }
- if (TREE_THIS_VOLATILE (var))
- {
- reject (var, "is volatile");
- return false;
- }
- if (!COMPLETE_TYPE_P (type))
- {
- reject (var, "has incomplete type");
- return false;
- }
- if (!tree_fits_shwi_p (TYPE_SIZE (type)))
- {
- reject (var, "type size not fixed");
- return false;
- }
- if (tree_to_shwi (TYPE_SIZE (type)) == 0)
- {
- reject (var, "type size is zero");
- return false;
- }
- if (type_internals_preclude_sra_p (type, &msg))
- {
- reject (var, msg);
- return false;
- }
- if (/* Fix for PR 41089. tree-stdarg.c needs to have va_lists intact but
- we also want to schedule it rather late. Thus we ignore it in
- the early pass. */
- (sra_mode == SRA_MODE_EARLY_INTRA
- && is_va_list_type (type)))
- {
- reject (var, "is va_list");
- return false;
- }
-
- bitmap_set_bit (candidate_bitmap, DECL_UID (var));
- slot = candidates->find_slot_with_hash (var, DECL_UID (var), INSERT);
- *slot = var;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
- print_generic_expr (dump_file, var);
- fprintf (dump_file, "\n");
- }
-
- return true;
-}
-
-/* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
- those with type which is suitable for scalarization. */
-
-static bool
-find_var_candidates (void)
-{
- tree var, parm;
- unsigned int i;
- bool ret = false;
-
- for (parm = DECL_ARGUMENTS (current_function_decl);
- parm;
- parm = DECL_CHAIN (parm))
- ret |= maybe_add_sra_candidate (parm);
-
- FOR_EACH_LOCAL_DECL (cfun, i, var)
- {
- if (!VAR_P (var))
- continue;
-
- ret |= maybe_add_sra_candidate (var);
- }
-
- return ret;
-}
-
-/* Return true if EXP is a reference chain of COMPONENT_REFs and AREAY_REFs
- ending either with a DECL or a MEM_REF with zero offset. */
-
-static bool
-path_comparable_for_same_access (tree expr)
-{
- while (handled_component_p (expr))
- {
- if (TREE_CODE (expr) == ARRAY_REF)
- {
- /* SSA name indices can occur here too when the array is of sie one.
- But we cannot just re-use array_refs with SSA names elsewhere in
- the function, so disallow non-constant indices. TODO: Remove this
- limitation after teaching build_reconstructed_reference to replace
- the index with the index type lower bound. */
- if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST)
- return false;
- }
- expr = TREE_OPERAND (expr, 0);
- }
-
- if (TREE_CODE (expr) == MEM_REF)
- {
- if (!zerop (TREE_OPERAND (expr, 1)))
- return false;
- }
- else
- gcc_assert (DECL_P (expr));
-
- return true;
-}
-
-/* Assuming that EXP1 consists of only COMPONENT_REFs and ARRAY_REFs, return
- true if the chain of these handled components are exactly the same as EXP2
- and the expression under them is the same DECL or an equivalent MEM_REF.
- The reference picked by compare_access_positions must go to EXP1. */
-
-static bool
-same_access_path_p (tree exp1, tree exp2)
-{
- if (TREE_CODE (exp1) != TREE_CODE (exp2))
- {
- /* Special case single-field structures loaded sometimes as the field
- and sometimes as the structure. If the field is of a scalar type,
- compare_access_positions will put it into exp1.
-
- TODO: The gimple register type condition can be removed if teach
- compare_access_positions to put inner types first. */
- if (is_gimple_reg_type (TREE_TYPE (exp1))
- && TREE_CODE (exp1) == COMPONENT_REF
- && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (exp1, 0)))
- == TYPE_MAIN_VARIANT (TREE_TYPE (exp2))))
- exp1 = TREE_OPERAND (exp1, 0);
- else
- return false;
- }
-
- if (!operand_equal_p (exp1, exp2, OEP_ADDRESS_OF))
- return false;
-
- return true;
-}
-
-/* Sort all accesses for the given variable, check for partial overlaps and
- return NULL if there are any. If there are none, pick a representative for
- each combination of offset and size and create a linked list out of them.
- Return the pointer to the first representative and make sure it is the first
- one in the vector of accesses. */
-
-static struct access *
-sort_and_splice_var_accesses (tree var)
-{
- int i, j, access_count;
- struct access *res, **prev_acc_ptr = &res;
- vec<access_p> *access_vec;
- bool first = true;
- HOST_WIDE_INT low = -1, high = 0;
-
- access_vec = get_base_access_vector (var);
- if (!access_vec)
- return NULL;
- access_count = access_vec->length ();
-
- /* Sort by <OFFSET, SIZE>. */
- access_vec->qsort (compare_access_positions);
-
- i = 0;
- while (i < access_count)
- {
- struct access *access = (*access_vec)[i];
- bool grp_write = access->write;
- bool grp_read = !access->write;
- bool grp_scalar_write = access->write
- && is_gimple_reg_type (access->type);
- bool grp_scalar_read = !access->write
- && is_gimple_reg_type (access->type);
- bool grp_assignment_read = access->grp_assignment_read;
- bool grp_assignment_write = access->grp_assignment_write;
- bool multiple_scalar_reads = false;
- bool grp_partial_lhs = access->grp_partial_lhs;
- bool first_scalar = is_gimple_reg_type (access->type);
- bool unscalarizable_region = access->grp_unscalarizable_region;
- bool grp_same_access_path = true;
- bool bf_non_full_precision
- = (INTEGRAL_TYPE_P (access->type)
- && TYPE_PRECISION (access->type) != access->size
- && TREE_CODE (access->expr) == COMPONENT_REF
- && DECL_BIT_FIELD (TREE_OPERAND (access->expr, 1)));
-
- if (first || access->offset >= high)
- {
- first = false;
- low = access->offset;
- high = access->offset + access->size;
- }
- else if (access->offset > low && access->offset + access->size > high)
- return NULL;
- else
- gcc_assert (access->offset >= low
- && access->offset + access->size <= high);
-
- grp_same_access_path = path_comparable_for_same_access (access->expr);
-
- j = i + 1;
- while (j < access_count)
- {
- struct access *ac2 = (*access_vec)[j];
- if (ac2->offset != access->offset || ac2->size != access->size)
- break;
- if (ac2->write)
- {
- grp_write = true;
- grp_scalar_write = (grp_scalar_write
- || is_gimple_reg_type (ac2->type));
- }
- else
- {
- grp_read = true;
- if (is_gimple_reg_type (ac2->type))
- {
- if (grp_scalar_read)
- multiple_scalar_reads = true;
- else
- grp_scalar_read = true;
- }
- }
- grp_assignment_read |= ac2->grp_assignment_read;
- grp_assignment_write |= ac2->grp_assignment_write;
- grp_partial_lhs |= ac2->grp_partial_lhs;
- unscalarizable_region |= ac2->grp_unscalarizable_region;
- relink_to_new_repr (access, ac2);
-
- /* If there are both aggregate-type and scalar-type accesses with
- this combination of size and offset, the comparison function
- should have put the scalars first. */
- gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
- /* It also prefers integral types to non-integral. However, when the
- precision of the selected type does not span the entire area and
- should also be used for a non-integer (i.e. float), we must not
- let that happen. Normally analyze_access_subtree expands the type
- to cover the entire area but for bit-fields it doesn't. */
- if (bf_non_full_precision && !INTEGRAL_TYPE_P (ac2->type))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Cannot scalarize the following access "
- "because insufficient precision integer type was "
- "selected.\n ");
- dump_access (dump_file, access, false);
- }
- unscalarizable_region = true;
- }
-
- if (grp_same_access_path
- && !same_access_path_p (access->expr, ac2->expr))
- grp_same_access_path = false;
-
- ac2->group_representative = access;
- j++;
- }
-
- i = j;
-
- access->group_representative = access;
- access->grp_write = grp_write;
- access->grp_read = grp_read;
- access->grp_scalar_read = grp_scalar_read;
- access->grp_scalar_write = grp_scalar_write;
- access->grp_assignment_read = grp_assignment_read;
- access->grp_assignment_write = grp_assignment_write;
- access->grp_hint = multiple_scalar_reads && !constant_decl_p (var);
- access->grp_partial_lhs = grp_partial_lhs;
- access->grp_unscalarizable_region = unscalarizable_region;
- access->grp_same_access_path = grp_same_access_path;
-
- *prev_acc_ptr = access;
- prev_acc_ptr = &access->next_grp;
- }
-
- gcc_assert (res == (*access_vec)[0]);
- return res;
-}
-
-/* Create a variable for the given ACCESS which determines the type, name and a
- few other properties. Return the variable declaration and store it also to
- ACCESS->replacement. REG_TREE is used when creating a declaration to base a
- default-definition SSA name on in order to facilitate an uninitialized
- warning. It is used instead of the actual ACCESS type if that is not of a
- gimple register type. */
-
-static tree
-create_access_replacement (struct access *access, tree reg_type = NULL_TREE)
-{
- tree repl;
-
- tree type = access->type;
- if (reg_type && !is_gimple_reg_type (type))
- type = reg_type;
-
- if (access->grp_to_be_debug_replaced)
- {
- repl = create_tmp_var_raw (access->type);
- DECL_CONTEXT (repl) = current_function_decl;
- }
- else
- /* Drop any special alignment on the type if it's not on the main
- variant. This avoids issues with weirdo ABIs like AAPCS. */
- repl = create_tmp_var (build_qualified_type (TYPE_MAIN_VARIANT (type),
- TYPE_QUALS (type)), "SR");
- if (access->grp_partial_lhs
- && is_gimple_reg_type (type))
- DECL_NOT_GIMPLE_REG_P (repl) = 1;
-
- DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
- DECL_ARTIFICIAL (repl) = 1;
- DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
-
- if (DECL_NAME (access->base)
- && !DECL_IGNORED_P (access->base)
- && !DECL_ARTIFICIAL (access->base))
- {
- char *pretty_name = make_fancy_name (access->expr);
- tree debug_expr = unshare_expr_without_location (access->expr), d;
- bool fail = false;
-
- DECL_NAME (repl) = get_identifier (pretty_name);
- DECL_NAMELESS (repl) = 1;
- obstack_free (&name_obstack, pretty_name);
-
- /* Get rid of any SSA_NAMEs embedded in debug_expr,
- as DECL_DEBUG_EXPR isn't considered when looking for still
- used SSA_NAMEs and thus they could be freed. All debug info
- generation cares is whether something is constant or variable
- and that get_ref_base_and_extent works properly on the
- expression. It cannot handle accesses at a non-constant offset
- though, so just give up in those cases. */
- for (d = debug_expr;
- !fail && (handled_component_p (d) || TREE_CODE (d) == MEM_REF);
- d = TREE_OPERAND (d, 0))
- switch (TREE_CODE (d))
- {
- case ARRAY_REF:
- case ARRAY_RANGE_REF:
- if (TREE_OPERAND (d, 1)
- && TREE_CODE (TREE_OPERAND (d, 1)) != INTEGER_CST)
- fail = true;
- if (TREE_OPERAND (d, 3)
- && TREE_CODE (TREE_OPERAND (d, 3)) != INTEGER_CST)
- fail = true;
- /* FALLTHRU */
- case COMPONENT_REF:
- if (TREE_OPERAND (d, 2)
- && TREE_CODE (TREE_OPERAND (d, 2)) != INTEGER_CST)
- fail = true;
- break;
- case MEM_REF:
- if (TREE_CODE (TREE_OPERAND (d, 0)) != ADDR_EXPR)
- fail = true;
- else
- d = TREE_OPERAND (d, 0);
- break;
- default:
- break;
- }
- if (!fail)
- {
- SET_DECL_DEBUG_EXPR (repl, debug_expr);
- DECL_HAS_DEBUG_EXPR_P (repl) = 1;
- }
- if (access->grp_no_warning)
- suppress_warning (repl /* Be more selective! */);
- else
- copy_warning (repl, access->base);
- }
- else
- suppress_warning (repl /* Be more selective! */);
-
- if (dump_file)
- {
- if (access->grp_to_be_debug_replaced)
- {
- fprintf (dump_file, "Created a debug-only replacement for ");
- print_generic_expr (dump_file, access->base);
- fprintf (dump_file, " offset: %u, size: %u\n",
- (unsigned) access->offset, (unsigned) access->size);
- }
- else
- {
- fprintf (dump_file, "Created a replacement for ");
- print_generic_expr (dump_file, access->base);
- fprintf (dump_file, " offset: %u, size: %u: ",
- (unsigned) access->offset, (unsigned) access->size);
- print_generic_expr (dump_file, repl, TDF_UID);
- fprintf (dump_file, "\n");
- }
- }
- sra_stats.replacements++;
-
- return repl;
-}
-
-/* Return ACCESS scalar replacement, which must exist. */
-
-static inline tree
-get_access_replacement (struct access *access)
-{
- gcc_checking_assert (access->replacement_decl);
- return access->replacement_decl;
-}
-
-
-/* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
- linked list along the way. Stop when *ACCESS is NULL or the access pointed
- to it is not "within" the root. Return false iff some accesses partially
- overlap. */
-
-static bool
-build_access_subtree (struct access **access)
-{
- struct access *root = *access, *last_child = NULL;
- HOST_WIDE_INT limit = root->offset + root->size;
-
- *access = (*access)->next_grp;
- while (*access && (*access)->offset + (*access)->size <= limit)
- {
- if (!last_child)
- root->first_child = *access;
- else
- last_child->next_sibling = *access;
- last_child = *access;
- (*access)->parent = root;
- (*access)->grp_write |= root->grp_write;
-
- if (!build_access_subtree (access))
- return false;
- }
-
- if (*access && (*access)->offset < limit)
- return false;
-
- return true;
-}
-
-/* Build a tree of access representatives, ACCESS is the pointer to the first
- one, others are linked in a list by the next_grp field. Return false iff
- some accesses partially overlap. */
-
-static bool
-build_access_trees (struct access *access)
-{
- while (access)
- {
- struct access *root = access;
-
- if (!build_access_subtree (&access))
- return false;
- root->next_grp = access;
- }
- return true;
-}
-
-/* Traverse the access forest where ROOT is the first root and verify that
- various important invariants hold true. */
-
-DEBUG_FUNCTION void
-verify_sra_access_forest (struct access *root)
-{
- struct access *access = root;
- tree first_base = root->base;
- gcc_assert (DECL_P (first_base));
- do
- {
- gcc_assert (access->base == first_base);
- if (access->parent)
- gcc_assert (access->offset >= access->parent->offset
- && access->size <= access->parent->size);
- if (access->next_sibling)
- gcc_assert (access->next_sibling->offset
- >= access->offset + access->size);
-
- poly_int64 poffset, psize, pmax_size;
- bool reverse;
- tree base = get_ref_base_and_extent (access->expr, &poffset, &psize,
- &pmax_size, &reverse);
- HOST_WIDE_INT offset, size, max_size;
- if (!poffset.is_constant (&offset)
- || !psize.is_constant (&size)
- || !pmax_size.is_constant (&max_size))
- gcc_unreachable ();
- gcc_assert (base == first_base);
- gcc_assert (offset == access->offset);
- gcc_assert (access->grp_unscalarizable_region
- || access->grp_total_scalarization
- || size == max_size);
- gcc_assert (access->grp_unscalarizable_region
- || !is_gimple_reg_type (access->type)
- || size == access->size);
- gcc_assert (reverse == access->reverse);
-
- if (access->first_child)
- {
- gcc_assert (access->first_child->parent == access);
- access = access->first_child;
- }
- else if (access->next_sibling)
- {
- gcc_assert (access->next_sibling->parent == access->parent);
- access = access->next_sibling;
- }
- else
- {
- while (access->parent && !access->next_sibling)
- access = access->parent;
- if (access->next_sibling)
- access = access->next_sibling;
- else
- {
- gcc_assert (access == root);
- root = root->next_grp;
- access = root;
- }
- }
- }
- while (access);
-}
-
-/* Verify access forests of all candidates with accesses by calling
- verify_access_forest on each on them. */
-
-DEBUG_FUNCTION void
-verify_all_sra_access_forests (void)
-{
- bitmap_iterator bi;
- unsigned i;
- EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
- {
- tree var = candidate (i);
- struct access *access = get_first_repr_for_decl (var);
- if (access)
- {
- gcc_assert (access->base == var);
- verify_sra_access_forest (access);
- }
- }
-}
-
-/* Return true if expr contains some ARRAY_REFs into a variable bounded
- array. */
-
-static bool
-expr_with_var_bounded_array_refs_p (tree expr)
-{
- while (handled_component_p (expr))
- {
- if (TREE_CODE (expr) == ARRAY_REF
- && !tree_fits_shwi_p (array_ref_low_bound (expr)))
- return true;
- expr = TREE_OPERAND (expr, 0);
- }
- return false;
-}
-
-/* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
- both seeming beneficial and when ALLOW_REPLACEMENTS allows it. If TOTALLY
- is set, we are totally scalarizing the aggregate. Also set all sorts of
- access flags appropriately along the way, notably always set grp_read and
- grp_assign_read according to MARK_READ and grp_write when MARK_WRITE is
- true.
-
- Creating a replacement for a scalar access is considered beneficial if its
- grp_hint ot TOTALLY is set (this means either that there is more than one
- direct read access or that we are attempting total scalarization) or
- according to the following table:
-
- Access written to through a scalar type (once or more times)
- |
- | Written to in an assignment statement
- | |
- | | Access read as scalar _once_
- | | |
- | | | Read in an assignment statement
- | | | |
- | | | | Scalarize Comment
------------------------------------------------------------------------------
- 0 0 0 0 No access for the scalar
- 0 0 0 1 No access for the scalar
- 0 0 1 0 No Single read - won't help
- 0 0 1 1 No The same case
- 0 1 0 0 No access for the scalar
- 0 1 0 1 No access for the scalar
- 0 1 1 0 Yes s = *g; return s.i;
- 0 1 1 1 Yes The same case as above
- 1 0 0 0 No Won't help
- 1 0 0 1 Yes s.i = 1; *g = s;
- 1 0 1 0 Yes s.i = 5; g = s.i;
- 1 0 1 1 Yes The same case as above
- 1 1 0 0 No Won't help.
- 1 1 0 1 Yes s.i = 1; *g = s;
- 1 1 1 0 Yes s = *g; return s.i;
- 1 1 1 1 Yes Any of the above yeses */
-
-static bool
-analyze_access_subtree (struct access *root, struct access *parent,
- bool allow_replacements, bool totally)
-{
- struct access *child;
- HOST_WIDE_INT limit = root->offset + root->size;
- HOST_WIDE_INT covered_to = root->offset;
- bool scalar = is_gimple_reg_type (root->type);
- bool hole = false, sth_created = false;
-
- if (parent)
- {
- if (parent->grp_read)
- root->grp_read = 1;
- if (parent->grp_assignment_read)
- root->grp_assignment_read = 1;
- if (parent->grp_write)
- root->grp_write = 1;
- if (parent->grp_assignment_write)
- root->grp_assignment_write = 1;
- if (!parent->grp_same_access_path)
- root->grp_same_access_path = 0;
- }
-
- if (root->grp_unscalarizable_region)
- allow_replacements = false;
-
- if (allow_replacements && expr_with_var_bounded_array_refs_p (root->expr))
- allow_replacements = false;
-
- for (child = root->first_child; child; child = child->next_sibling)
- {
- hole |= covered_to < child->offset;
- sth_created |= analyze_access_subtree (child, root,
- allow_replacements && !scalar,
- totally);
-
- root->grp_unscalarized_data |= child->grp_unscalarized_data;
- if (child->grp_covered)
- covered_to += child->size;
- else
- hole = true;
- }
-
- if (allow_replacements && scalar && !root->first_child
- && (totally || !root->grp_total_scalarization)
- && (totally
- || root->grp_hint
- || ((root->grp_scalar_read || root->grp_assignment_read)
- && (root->grp_scalar_write || root->grp_assignment_write))))
- {
- /* Always create access replacements that cover the whole access.
- For integral types this means the precision has to match.
- Avoid assumptions based on the integral type kind, too. */
- if (INTEGRAL_TYPE_P (root->type)
- && (TREE_CODE (root->type) != INTEGER_TYPE
- || TYPE_PRECISION (root->type) != root->size)
- /* But leave bitfield accesses alone. */
- && (TREE_CODE (root->expr) != COMPONENT_REF
- || !DECL_BIT_FIELD (TREE_OPERAND (root->expr, 1))))
- {
- tree rt = root->type;
- gcc_assert ((root->offset % BITS_PER_UNIT) == 0
- && (root->size % BITS_PER_UNIT) == 0);
- root->type = build_nonstandard_integer_type (root->size,
- TYPE_UNSIGNED (rt));
- root->expr = build_ref_for_offset (UNKNOWN_LOCATION, root->base,
- root->offset, root->reverse,
- root->type, NULL, false);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Changing the type of a replacement for ");
- print_generic_expr (dump_file, root->base);
- fprintf (dump_file, " offset: %u, size: %u ",
- (unsigned) root->offset, (unsigned) root->size);
- fprintf (dump_file, " to an integer.\n");
- }
- }
-
- root->grp_to_be_replaced = 1;
- root->replacement_decl = create_access_replacement (root);
- sth_created = true;
- hole = false;
- }
- else
- {
- if (allow_replacements
- && scalar && !root->first_child
- && !root->grp_total_scalarization
- && (root->grp_scalar_write || root->grp_assignment_write)
- && !bitmap_bit_p (cannot_scalarize_away_bitmap,
- DECL_UID (root->base)))
- {
- gcc_checking_assert (!root->grp_scalar_read
- && !root->grp_assignment_read);
- sth_created = true;
- if (MAY_HAVE_DEBUG_BIND_STMTS)
- {
- root->grp_to_be_debug_replaced = 1;
- root->replacement_decl = create_access_replacement (root);
- }
- }
-
- if (covered_to < limit)
- hole = true;
- if (scalar || !allow_replacements)
- root->grp_total_scalarization = 0;
- }
-
- if (!hole || totally)
- root->grp_covered = 1;
- else if (root->grp_write || comes_initialized_p (root->base))
- root->grp_unscalarized_data = 1; /* not covered and written to */
- return sth_created;
-}
-
-/* Analyze all access trees linked by next_grp by the means of
- analyze_access_subtree. */
-static bool
-analyze_access_trees (struct access *access)
-{
- bool ret = false;
-
- while (access)
- {
- if (analyze_access_subtree (access, NULL, true,
- access->grp_total_scalarization))
- ret = true;
- access = access->next_grp;
- }
-
- return ret;
-}
-
-/* Return true iff a potential new child of ACC at offset OFFSET and with size
- SIZE would conflict with an already existing one. If exactly such a child
- already exists in ACC, store a pointer to it in EXACT_MATCH. */
-
-static bool
-child_would_conflict_in_acc (struct access *acc, HOST_WIDE_INT norm_offset,
- HOST_WIDE_INT size, struct access **exact_match)
-{
- struct access *child;
-
- for (child = acc->first_child; child; child = child->next_sibling)
- {
- if (child->offset == norm_offset && child->size == size)
- {
- *exact_match = child;
- return true;
- }
-
- if (child->offset < norm_offset + size
- && child->offset + child->size > norm_offset)
- return true;
- }
-
- return false;
-}
-
-/* Create a new child access of PARENT, with all properties just like MODEL
- except for its offset and with its grp_write false and grp_read true.
- Return the new access or NULL if it cannot be created. Note that this
- access is created long after all splicing and sorting, it's not located in
- any access vector and is automatically a representative of its group. Set
- the gpr_write flag of the new accesss if SET_GRP_WRITE is true. */
-
-static struct access *
-create_artificial_child_access (struct access *parent, struct access *model,
- HOST_WIDE_INT new_offset,
- bool set_grp_read, bool set_grp_write)
-{
- struct access **child;
- tree expr = parent->base;
-
- gcc_assert (!model->grp_unscalarizable_region);
-
- struct access *access = access_pool.allocate ();
- memset (access, 0, sizeof (struct access));
- if (!build_user_friendly_ref_for_offset (&expr, TREE_TYPE (expr), new_offset,
- model->type))
- {
- access->grp_no_warning = true;
- expr = build_ref_for_model (EXPR_LOCATION (parent->base), parent->base,
- new_offset, model, NULL, false);
- }
-
- access->base = parent->base;
- access->expr = expr;
- access->offset = new_offset;
- access->size = model->size;
- access->type = model->type;
- access->parent = parent;
- access->grp_read = set_grp_read;
- access->grp_write = set_grp_write;
- access->reverse = model->reverse;
-
- child = &parent->first_child;
- while (*child && (*child)->offset < new_offset)
- child = &(*child)->next_sibling;
-
- access->next_sibling = *child;
- *child = access;
-
- return access;
-}
-
-
-/* Beginning with ACCESS, traverse its whole access subtree and mark all
- sub-trees as written to. If any of them has not been marked so previously
- and has assignment links leading from it, re-enqueue it. */
-
-static void
-subtree_mark_written_and_rhs_enqueue (struct access *access)
-{
- if (access->grp_write)
- return;
- access->grp_write = true;
- add_access_to_rhs_work_queue (access);
-
- struct access *child;
- for (child = access->first_child; child; child = child->next_sibling)
- subtree_mark_written_and_rhs_enqueue (child);
-}
-
-/* If there is still budget to create a propagation access for DECL, return
- true and decrement the budget. Otherwise return false. */
-
-static bool
-budget_for_propagation_access (tree decl)
-{
- unsigned b, *p = propagation_budget->get (decl);
- if (p)
- b = *p;
- else
- b = param_sra_max_propagations;
-
- if (b == 0)
- return false;
- b--;
-
- if (b == 0 && dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "The propagation budget of ");
- print_generic_expr (dump_file, decl);
- fprintf (dump_file, " (UID: %u) has been exhausted.\n", DECL_UID (decl));
- }
- propagation_budget->put (decl, b);
- return true;
-}
-
-/* Return true if ACC or any of its subaccesses has grp_child set. */
-
-static bool
-access_or_its_child_written (struct access *acc)
-{
- if (acc->grp_write)
- return true;
- for (struct access *sub = acc->first_child; sub; sub = sub->next_sibling)
- if (access_or_its_child_written (sub))
- return true;
- return false;
-}
-
-/* Propagate subaccesses and grp_write flags of RACC across an assignment link
- to LACC. Enqueue sub-accesses as necessary so that the write flag is
- propagated transitively. Return true if anything changed. Additionally, if
- RACC is a scalar access but LACC is not, change the type of the latter, if
- possible. */
-
-static bool
-propagate_subaccesses_from_rhs (struct access *lacc, struct access *racc)
-{
- struct access *rchild;
- HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
- bool ret = false;
-
- /* IF the LHS is still not marked as being written to, we only need to do so
- if the RHS at this level actually was. */
- if (!lacc->grp_write)
- {
- gcc_checking_assert (!comes_initialized_p (racc->base));
- if (racc->grp_write)
- {
- subtree_mark_written_and_rhs_enqueue (lacc);
- ret = true;
- }
- }
-
- if (is_gimple_reg_type (lacc->type)
- || lacc->grp_unscalarizable_region
- || racc->grp_unscalarizable_region)
- {
- if (!lacc->grp_write)
- {
- ret = true;
- subtree_mark_written_and_rhs_enqueue (lacc);
- }
- return ret;
- }
-
- if (is_gimple_reg_type (racc->type))
- {
- if (!lacc->grp_write)
- {
- ret = true;
- subtree_mark_written_and_rhs_enqueue (lacc);
- }
- if (!lacc->first_child && !racc->first_child)
- {
- /* We are about to change the access type from aggregate to scalar,
- so we need to put the reverse flag onto the access, if any. */
- const bool reverse
- = TYPE_REVERSE_STORAGE_ORDER (lacc->type)
- && !POINTER_TYPE_P (racc->type)
- && !VECTOR_TYPE_P (racc->type);
- tree t = lacc->base;
-
- lacc->type = racc->type;
- if (build_user_friendly_ref_for_offset (&t, TREE_TYPE (t),
- lacc->offset, racc->type))
- {
- lacc->expr = t;
- lacc->grp_same_access_path = true;
- }
- else
- {
- lacc->expr = build_ref_for_model (EXPR_LOCATION (lacc->base),
- lacc->base, lacc->offset,
- racc, NULL, false);
- if (TREE_CODE (lacc->expr) == MEM_REF)
- REF_REVERSE_STORAGE_ORDER (lacc->expr) = reverse;
- lacc->grp_no_warning = true;
- lacc->grp_same_access_path = false;
- }
- lacc->reverse = reverse;
- }
- return ret;
- }
-
- for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
- {
- struct access *new_acc = NULL;
- HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
-
- if (child_would_conflict_in_acc (lacc, norm_offset, rchild->size,
- &new_acc))
- {
- if (new_acc)
- {
- if (!new_acc->grp_write && rchild->grp_write)
- {
- gcc_assert (!lacc->grp_write);
- subtree_mark_written_and_rhs_enqueue (new_acc);
- ret = true;
- }
-
- rchild->grp_hint = 1;
- new_acc->grp_hint |= new_acc->grp_read;
- if (rchild->first_child
- && propagate_subaccesses_from_rhs (new_acc, rchild))
- {
- ret = 1;
- add_access_to_rhs_work_queue (new_acc);
- }
- }
- else
- {
- if (!lacc->grp_write)
- {
- ret = true;
- subtree_mark_written_and_rhs_enqueue (lacc);
- }
- }
- continue;
- }
-
- if (rchild->grp_unscalarizable_region
- || !budget_for_propagation_access (lacc->base))
- {
- if (!lacc->grp_write && access_or_its_child_written (rchild))
- {
- ret = true;
- subtree_mark_written_and_rhs_enqueue (lacc);
- }
- continue;
- }
-
- rchild->grp_hint = 1;
- /* Because get_ref_base_and_extent always includes padding in size for
- accesses to DECLs but not necessarily for COMPONENT_REFs of the same
- type, we might be actually attempting to here to create a child of the
- same type as the parent. */
- if (!types_compatible_p (lacc->type, rchild->type))
- new_acc = create_artificial_child_access (lacc, rchild, norm_offset,
- false,
- (lacc->grp_write
- || rchild->grp_write));
- else
- new_acc = lacc;
- gcc_checking_assert (new_acc);
- if (racc->first_child)
- propagate_subaccesses_from_rhs (new_acc, rchild);
-
- add_access_to_rhs_work_queue (lacc);
- ret = true;
- }
-
- return ret;
-}
-
-/* Propagate subaccesses of LACC across an assignment link to RACC if they
- should inhibit total scalarization of the corresponding area. No flags are
- being propagated in the process. Return true if anything changed. */
-
-static bool
-propagate_subaccesses_from_lhs (struct access *lacc, struct access *racc)
-{
- if (is_gimple_reg_type (racc->type)
- || lacc->grp_unscalarizable_region
- || racc->grp_unscalarizable_region)
- return false;
-
- /* TODO: Do we want set some new racc flag to stop potential total
- scalarization if lacc is a scalar access (and none fo the two have
- children)? */
-
- bool ret = false;
- HOST_WIDE_INT norm_delta = racc->offset - lacc->offset;
- for (struct access *lchild = lacc->first_child;
- lchild;
- lchild = lchild->next_sibling)
- {
- struct access *matching_acc = NULL;
- HOST_WIDE_INT norm_offset = lchild->offset + norm_delta;
-
- if (lchild->grp_unscalarizable_region
- || child_would_conflict_in_acc (racc, norm_offset, lchild->size,
- &matching_acc)
- || !budget_for_propagation_access (racc->base))
- {
- if (matching_acc
- && propagate_subaccesses_from_lhs (lchild, matching_acc))
- add_access_to_lhs_work_queue (matching_acc);
- continue;
- }
-
- /* Because get_ref_base_and_extent always includes padding in size for
- accesses to DECLs but not necessarily for COMPONENT_REFs of the same
- type, we might be actually attempting to here to create a child of the
- same type as the parent. */
- if (!types_compatible_p (racc->type, lchild->type))
- {
- struct access *new_acc
- = create_artificial_child_access (racc, lchild, norm_offset,
- true, false);
- propagate_subaccesses_from_lhs (lchild, new_acc);
- }
- else
- propagate_subaccesses_from_lhs (lchild, racc);
- ret = true;
- }
- return ret;
-}
-
-/* Propagate all subaccesses across assignment links. */
-
-static void
-propagate_all_subaccesses (void)
-{
- propagation_budget = new hash_map<tree, unsigned>;
- while (rhs_work_queue_head)
- {
- struct access *racc = pop_access_from_rhs_work_queue ();
- struct assign_link *link;
-
- if (racc->group_representative)
- racc= racc->group_representative;
- gcc_assert (racc->first_rhs_link);
-
- for (link = racc->first_rhs_link; link; link = link->next_rhs)
- {
- struct access *lacc = link->lacc;
-
- if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
- continue;
- lacc = lacc->group_representative;
-
- bool reque_parents = false;
- if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
- {
- if (!lacc->grp_write)
- {
- subtree_mark_written_and_rhs_enqueue (lacc);
- reque_parents = true;
- }
- }
- else if (propagate_subaccesses_from_rhs (lacc, racc))
- reque_parents = true;
-
- if (reque_parents)
- do
- {
- add_access_to_rhs_work_queue (lacc);
- lacc = lacc->parent;
- }
- while (lacc);
- }
- }
-
- while (lhs_work_queue_head)
- {
- struct access *lacc = pop_access_from_lhs_work_queue ();
- struct assign_link *link;
-
- if (lacc->group_representative)
- lacc = lacc->group_representative;
- gcc_assert (lacc->first_lhs_link);
-
- if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
- continue;
-
- for (link = lacc->first_lhs_link; link; link = link->next_lhs)
- {
- struct access *racc = link->racc;
-
- if (racc->group_representative)
- racc = racc->group_representative;
- if (!bitmap_bit_p (candidate_bitmap, DECL_UID (racc->base)))
- continue;
- if (propagate_subaccesses_from_lhs (lacc, racc))
- add_access_to_lhs_work_queue (racc);
- }
- }
- delete propagation_budget;
-}
-
-/* Return true if the forest beginning with ROOT does not contain
- unscalarizable regions or non-byte aligned accesses. */
-
-static bool
-can_totally_scalarize_forest_p (struct access *root)
-{
- struct access *access = root;
- do
- {
- if (access->grp_unscalarizable_region
- || (access->offset % BITS_PER_UNIT) != 0
- || (access->size % BITS_PER_UNIT) != 0
- || (is_gimple_reg_type (access->type)
- && access->first_child))
- return false;
-
- if (access->first_child)
- access = access->first_child;
- else if (access->next_sibling)
- access = access->next_sibling;
- else
- {
- while (access->parent && !access->next_sibling)
- access = access->parent;
- if (access->next_sibling)
- access = access->next_sibling;
- else
- {
- gcc_assert (access == root);
- root = root->next_grp;
- access = root;
- }
- }
- }
- while (access);
- return true;
-}
-
-/* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
- reference EXPR for total scalarization purposes and mark it as such. Within
- the children of PARENT, link it in between PTR and NEXT_SIBLING. */
-
-static struct access *
-create_total_scalarization_access (struct access *parent, HOST_WIDE_INT pos,
- HOST_WIDE_INT size, tree type, tree expr,
- struct access **ptr,
- struct access *next_sibling)
-{
- struct access *access = access_pool.allocate ();
- memset (access, 0, sizeof (struct access));
- access->base = parent->base;
- access->offset = pos;
- access->size = size;
- access->expr = expr;
- access->type = type;
- access->parent = parent;
- access->grp_write = parent->grp_write;
- access->grp_total_scalarization = 1;
- access->grp_hint = 1;
- access->grp_same_access_path = path_comparable_for_same_access (expr);
- access->reverse = reverse_storage_order_for_component_p (expr);
-
- access->next_sibling = next_sibling;
- *ptr = access;
- return access;
-}
-
-/* Create and return an ACCESS in PARENT spanning from POS with SIZE, TYPE and
- reference EXPR for total scalarization purposes and mark it as such, link it
- at *PTR and reshape the tree so that those elements at *PTR and their
- siblings which fall within the part described by POS and SIZE are moved to
- be children of the new access. If a partial overlap is detected, return
- NULL. */
-
-static struct access *
-create_total_access_and_reshape (struct access *parent, HOST_WIDE_INT pos,
- HOST_WIDE_INT size, tree type, tree expr,
- struct access **ptr)
-{
- struct access **p = ptr;
-
- while (*p && (*p)->offset < pos + size)
- {
- if ((*p)->offset + (*p)->size > pos + size)
- return NULL;
- p = &(*p)->next_sibling;
- }
-
- struct access *next_child = *ptr;
- struct access *new_acc
- = create_total_scalarization_access (parent, pos, size, type, expr,
- ptr, *p);
- if (p != ptr)
- {
- new_acc->first_child = next_child;
- *p = NULL;
- for (struct access *a = next_child; a; a = a->next_sibling)
- a->parent = new_acc;
- }
- return new_acc;
-}
-
-static bool totally_scalarize_subtree (struct access *root);
-
-/* Return true if INNER is either the same type as OUTER or if it is the type
- of a record field in OUTER at offset zero, possibly in nested
- sub-records. */
-
-static bool
-access_and_field_type_match_p (tree outer, tree inner)
-{
- if (TYPE_MAIN_VARIANT (outer) == TYPE_MAIN_VARIANT (inner))
- return true;
- if (TREE_CODE (outer) != RECORD_TYPE)
- return false;
- tree fld = TYPE_FIELDS (outer);
- while (fld)
- {
- if (TREE_CODE (fld) == FIELD_DECL)
- {
- if (!zerop (DECL_FIELD_OFFSET (fld)))
- return false;
- if (TYPE_MAIN_VARIANT (TREE_TYPE (fld)) == inner)
- return true;
- if (TREE_CODE (TREE_TYPE (fld)) == RECORD_TYPE)
- fld = TYPE_FIELDS (TREE_TYPE (fld));
- else
- return false;
- }
- else
- fld = DECL_CHAIN (fld);
- }
- return false;
-}
-
-/* Return type of total_should_skip_creating_access indicating whether a total
- scalarization access for a field/element should be created, whether it
- already exists or whether the entire total scalarization has to fail. */
-
-enum total_sra_field_state {TOTAL_FLD_CREATE, TOTAL_FLD_DONE, TOTAL_FLD_FAILED};
-
-/* Do all the necessary steps in total scalarization when the given aggregate
- type has a TYPE at POS with the given SIZE should be put into PARENT and
- when we have processed all its siblings with smaller offsets up until and
- including LAST_SEEN_SIBLING (which can be NULL).
-
- If some further siblings are to be skipped, set *LAST_SEEN_SIBLING as
- appropriate. Return TOTAL_FLD_CREATE id the caller should carry on with
- creating a new access, TOTAL_FLD_DONE if access or accesses capable of
- representing the described part of the aggregate for the purposes of total
- scalarization already exist or TOTAL_FLD_FAILED if there is a problem which
- prevents total scalarization from happening at all. */
-
-static enum total_sra_field_state
-total_should_skip_creating_access (struct access *parent,
- struct access **last_seen_sibling,
- tree type, HOST_WIDE_INT pos,
- HOST_WIDE_INT size)
-{
- struct access *next_child;
- if (!*last_seen_sibling)
- next_child = parent->first_child;
- else
- next_child = (*last_seen_sibling)->next_sibling;
-
- /* First, traverse the chain of siblings until it points to an access with
- offset at least equal to POS. Check all skipped accesses whether they
- span the POS boundary and if so, return with a failure. */
- while (next_child && next_child->offset < pos)
- {
- if (next_child->offset + next_child->size > pos)
- return TOTAL_FLD_FAILED;
- *last_seen_sibling = next_child;
- next_child = next_child->next_sibling;
- }
-
- /* Now check whether next_child has exactly the right POS and SIZE and if so,
- whether it can represent what we need and can be totally scalarized
- itself. */
- if (next_child && next_child->offset == pos
- && next_child->size == size)
- {
- if (!is_gimple_reg_type (next_child->type)
- && (!access_and_field_type_match_p (type, next_child->type)
- || !totally_scalarize_subtree (next_child)))
- return TOTAL_FLD_FAILED;
-
- *last_seen_sibling = next_child;
- return TOTAL_FLD_DONE;
- }
-
- /* If the child we're looking at would partially overlap, we just cannot
- totally scalarize. */
- if (next_child
- && next_child->offset < pos + size
- && next_child->offset + next_child->size > pos + size)
- return TOTAL_FLD_FAILED;
-
- if (is_gimple_reg_type (type))
- {
- /* We don't scalarize accesses that are children of other scalar type
- accesses, so if we go on and create an access for a register type,
- there should not be any pre-existing children. There are rare cases
- where the requested type is a vector but we already have register
- accesses for all its elements which is equally good. Detect that
- situation or whether we need to bail out. */
-
- HOST_WIDE_INT covered = pos;
- bool skipping = false;
- while (next_child
- && next_child->offset + next_child->size <= pos + size)
- {
- if (next_child->offset != covered
- || !is_gimple_reg_type (next_child->type))
- return TOTAL_FLD_FAILED;
-
- covered += next_child->size;
- *last_seen_sibling = next_child;
- next_child = next_child->next_sibling;
- skipping = true;
- }
-
- if (skipping)
- {
- if (covered != pos + size)
- return TOTAL_FLD_FAILED;
- else
- return TOTAL_FLD_DONE;
- }
- }
-
- return TOTAL_FLD_CREATE;
-}
-
-/* Go over sub-tree rooted in ROOT and attempt to create scalar accesses
- spanning all uncovered areas covered by ROOT, return false if the attempt
- failed. All created accesses will have grp_unscalarizable_region set (and
- should be ignored if the function returns false). */
-
-static bool
-totally_scalarize_subtree (struct access *root)
-{
- gcc_checking_assert (!root->grp_unscalarizable_region);
- gcc_checking_assert (!is_gimple_reg_type (root->type));
-
- struct access *last_seen_sibling = NULL;
-
- switch (TREE_CODE (root->type))
- {
- case RECORD_TYPE:
- for (tree fld = TYPE_FIELDS (root->type); fld; fld = DECL_CHAIN (fld))
- if (TREE_CODE (fld) == FIELD_DECL)
- {
- tree ft = TREE_TYPE (fld);
- HOST_WIDE_INT fsize = tree_to_uhwi (DECL_SIZE (fld));
- if (!fsize)
- continue;
-
- HOST_WIDE_INT pos = root->offset + int_bit_position (fld);
- if (pos + fsize > root->offset + root->size)
- return false;
- enum total_sra_field_state
- state = total_should_skip_creating_access (root,
- &last_seen_sibling,
- ft, pos, fsize);
- switch (state)
- {
- case TOTAL_FLD_FAILED:
- return false;
- case TOTAL_FLD_DONE:
- continue;
- case TOTAL_FLD_CREATE:
- break;
- default:
- gcc_unreachable ();
- }
-
- struct access **p = (last_seen_sibling
- ? &last_seen_sibling->next_sibling
- : &root->first_child);
- tree nref = build3 (COMPONENT_REF, ft, root->expr, fld, NULL_TREE);
- struct access *new_child
- = create_total_access_and_reshape (root, pos, fsize, ft, nref, p);
- if (!new_child)
- return false;
-
- if (!is_gimple_reg_type (ft)
- && !totally_scalarize_subtree (new_child))
- return false;
- last_seen_sibling = new_child;
- }
- break;
- case ARRAY_TYPE:
- {
- tree elemtype = TREE_TYPE (root->type);
- tree elem_size = TYPE_SIZE (elemtype);
- gcc_assert (elem_size && tree_fits_shwi_p (elem_size));
- HOST_WIDE_INT el_size = tree_to_shwi (elem_size);
- gcc_assert (el_size > 0);
-
- tree minidx = TYPE_MIN_VALUE (TYPE_DOMAIN (root->type));
- gcc_assert (TREE_CODE (minidx) == INTEGER_CST);
- tree maxidx = TYPE_MAX_VALUE (TYPE_DOMAIN (root->type));
- /* Skip (some) zero-length arrays; others have MAXIDX == MINIDX - 1. */
- if (!maxidx)
- goto out;
- gcc_assert (TREE_CODE (maxidx) == INTEGER_CST);
- tree domain = TYPE_DOMAIN (root->type);
- /* MINIDX and MAXIDX are inclusive, and must be interpreted in
- DOMAIN (e.g. signed int, whereas min/max may be size_int). */
- offset_int idx = wi::to_offset (minidx);
- offset_int max = wi::to_offset (maxidx);
- if (!TYPE_UNSIGNED (domain))
- {
- idx = wi::sext (idx, TYPE_PRECISION (domain));
- max = wi::sext (max, TYPE_PRECISION (domain));
- }
- for (HOST_WIDE_INT pos = root->offset;
- idx <= max;
- pos += el_size, ++idx)
- {
- enum total_sra_field_state
- state = total_should_skip_creating_access (root,
- &last_seen_sibling,
- elemtype, pos,
- el_size);
- switch (state)
- {
- case TOTAL_FLD_FAILED:
- return false;
- case TOTAL_FLD_DONE:
- continue;
- case TOTAL_FLD_CREATE:
- break;
- default:
- gcc_unreachable ();
- }
-
- struct access **p = (last_seen_sibling
- ? &last_seen_sibling->next_sibling
- : &root->first_child);
- tree nref = build4 (ARRAY_REF, elemtype, root->expr,
- wide_int_to_tree (domain, idx),
- NULL_TREE, NULL_TREE);
- struct access *new_child
- = create_total_access_and_reshape (root, pos, el_size, elemtype,
- nref, p);
- if (!new_child)
- return false;
-
- if (!is_gimple_reg_type (elemtype)
- && !totally_scalarize_subtree (new_child))
- return false;
- last_seen_sibling = new_child;
- }
- }
- break;
- default:
- gcc_unreachable ();
- }
-
- out:
- return true;
-}
-
-/* Go through all accesses collected throughout the (intraprocedural) analysis
- stage, exclude overlapping ones, identify representatives and build trees
- out of them, making decisions about scalarization on the way. Return true
- iff there are any to-be-scalarized variables after this stage. */
-
-static bool
-analyze_all_variable_accesses (void)
-{
- int res = 0;
- bitmap tmp = BITMAP_ALLOC (NULL);
- bitmap_iterator bi;
- unsigned i;
-
- bitmap_copy (tmp, candidate_bitmap);
- EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
- {
- tree var = candidate (i);
- struct access *access;
-
- access = sort_and_splice_var_accesses (var);
- if (!access || !build_access_trees (access))
- disqualify_candidate (var,
- "No or inhibitingly overlapping accesses.");
- }
-
- propagate_all_subaccesses ();
-
- bool optimize_speed_p = !optimize_function_for_size_p (cfun);
- /* If the user didn't set PARAM_SRA_MAX_SCALARIZATION_SIZE_<...>,
- fall back to a target default. */
- unsigned HOST_WIDE_INT max_scalarization_size
- = get_move_ratio (optimize_speed_p) * UNITS_PER_WORD;
-
- if (optimize_speed_p)
- {
- if (OPTION_SET_P (param_sra_max_scalarization_size_speed))
- max_scalarization_size = param_sra_max_scalarization_size_speed;
- }
- else
- {
- if (OPTION_SET_P (param_sra_max_scalarization_size_size))
- max_scalarization_size = param_sra_max_scalarization_size_size;
- }
- max_scalarization_size *= BITS_PER_UNIT;
-
- EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
- if (bitmap_bit_p (should_scalarize_away_bitmap, i)
- && !bitmap_bit_p (cannot_scalarize_away_bitmap, i))
- {
- tree var = candidate (i);
- if (!VAR_P (var))
- continue;
-
- if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var))) > max_scalarization_size)
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Too big to totally scalarize: ");
- print_generic_expr (dump_file, var);
- fprintf (dump_file, " (UID: %u)\n", DECL_UID (var));
- }
- continue;
- }
-
- bool all_types_ok = true;
- for (struct access *access = get_first_repr_for_decl (var);
- access;
- access = access->next_grp)
- if (!can_totally_scalarize_forest_p (access)
- || !scalarizable_type_p (access->type, constant_decl_p (var)))
- {
- all_types_ok = false;
- break;
- }
- if (!all_types_ok)
- continue;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Will attempt to totally scalarize ");
- print_generic_expr (dump_file, var);
- fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
- }
- bool scalarized = true;
- for (struct access *access = get_first_repr_for_decl (var);
- access;
- access = access->next_grp)
- if (!is_gimple_reg_type (access->type)
- && !totally_scalarize_subtree (access))
- {
- scalarized = false;
- break;
- }
-
- if (scalarized)
- for (struct access *access = get_first_repr_for_decl (var);
- access;
- access = access->next_grp)
- access->grp_total_scalarization = true;
- }
-
- if (flag_checking)
- verify_all_sra_access_forests ();
-
- bitmap_copy (tmp, candidate_bitmap);
- EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
- {
- tree var = candidate (i);
- struct access *access = get_first_repr_for_decl (var);
-
- if (analyze_access_trees (access))
- {
- res++;
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "\nAccess trees for ");
- print_generic_expr (dump_file, var);
- fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
- dump_access_tree (dump_file, access);
- fprintf (dump_file, "\n");
- }
- }
- else
- disqualify_candidate (var, "No scalar replacements to be created.");
- }
-
- BITMAP_FREE (tmp);
-
- if (res)
- {
- statistics_counter_event (cfun, "Scalarized aggregates", res);
- return true;
- }
- else
- return false;
-}
-
-/* Generate statements copying scalar replacements of accesses within a subtree
- into or out of AGG. ACCESS, all its children, siblings and their children
- are to be processed. AGG is an aggregate type expression (can be a
- declaration but does not have to be, it can for example also be a mem_ref or
- a series of handled components). TOP_OFFSET is the offset of the processed
- subtree which has to be subtracted from offsets of individual accesses to
- get corresponding offsets for AGG. If CHUNK_SIZE is non-null, copy only
- replacements in the interval <start_offset, start_offset + chunk_size>,
- otherwise copy all. GSI is a statement iterator used to place the new
- statements. WRITE should be true when the statements should write from AGG
- to the replacement and false if vice versa. if INSERT_AFTER is true, new
- statements will be added after the current statement in GSI, they will be
- added before the statement otherwise. */
-
-static void
-generate_subtree_copies (struct access *access, tree agg,
- HOST_WIDE_INT top_offset,
- HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
- gimple_stmt_iterator *gsi, bool write,
- bool insert_after, location_t loc)
-{
- /* Never write anything into constant pool decls. See PR70602. */
- if (!write && constant_decl_p (agg))
- return;
- do
- {
- if (chunk_size && access->offset >= start_offset + chunk_size)
- return;
-
- if (access->grp_to_be_replaced
- && (chunk_size == 0
- || access->offset + access->size > start_offset))
- {
- tree expr, repl = get_access_replacement (access);
- gassign *stmt;
-
- expr = build_ref_for_model (loc, agg, access->offset - top_offset,
- access, gsi, insert_after);
-
- if (write)
- {
- if (access->grp_partial_lhs)
- expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
- !insert_after,
- insert_after ? GSI_NEW_STMT
- : GSI_SAME_STMT);
- stmt = gimple_build_assign (repl, expr);
- }
- else
- {
- suppress_warning (repl /* Be more selective! */);
- if (access->grp_partial_lhs)
- repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
- !insert_after,
- insert_after ? GSI_NEW_STMT
- : GSI_SAME_STMT);
- stmt = gimple_build_assign (expr, repl);
- }
- gimple_set_location (stmt, loc);
-
- if (insert_after)
- gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
- else
- gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
- update_stmt (stmt);
- sra_stats.subtree_copies++;
- }
- else if (write
- && access->grp_to_be_debug_replaced
- && (chunk_size == 0
- || access->offset + access->size > start_offset))
- {
- gdebug *ds;
- tree drhs = build_debug_ref_for_model (loc, agg,
- access->offset - top_offset,
- access);
- ds = gimple_build_debug_bind (get_access_replacement (access),
- drhs, gsi_stmt (*gsi));
- if (insert_after)
- gsi_insert_after (gsi, ds, GSI_NEW_STMT);
- else
- gsi_insert_before (gsi, ds, GSI_SAME_STMT);
- }
-
- if (access->first_child)
- generate_subtree_copies (access->first_child, agg, top_offset,
- start_offset, chunk_size, gsi,
- write, insert_after, loc);
-
- access = access->next_sibling;
- }
- while (access);
-}
-
-/* Assign zero to all scalar replacements in an access subtree. ACCESS is the
- root of the subtree to be processed. GSI is the statement iterator used
- for inserting statements which are added after the current statement if
- INSERT_AFTER is true or before it otherwise. */
-
-static void
-init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
- bool insert_after, location_t loc)
-
-{
- struct access *child;
-
- if (access->grp_to_be_replaced)
- {
- gassign *stmt;
-
- stmt = gimple_build_assign (get_access_replacement (access),
- build_zero_cst (access->type));
- if (insert_after)
- gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
- else
- gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
- update_stmt (stmt);
- gimple_set_location (stmt, loc);
- }
- else if (access->grp_to_be_debug_replaced)
- {
- gdebug *ds
- = gimple_build_debug_bind (get_access_replacement (access),
- build_zero_cst (access->type),
- gsi_stmt (*gsi));
- if (insert_after)
- gsi_insert_after (gsi, ds, GSI_NEW_STMT);
- else
- gsi_insert_before (gsi, ds, GSI_SAME_STMT);
- }
-
- for (child = access->first_child; child; child = child->next_sibling)
- init_subtree_with_zero (child, gsi, insert_after, loc);
-}
-
-/* Clobber all scalar replacements in an access subtree. ACCESS is the
- root of the subtree to be processed. GSI is the statement iterator used
- for inserting statements which are added after the current statement if
- INSERT_AFTER is true or before it otherwise. */
-
-static void
-clobber_subtree (struct access *access, gimple_stmt_iterator *gsi,
- bool insert_after, location_t loc)
-
-{
- struct access *child;
-
- if (access->grp_to_be_replaced)
- {
- tree rep = get_access_replacement (access);
- tree clobber = build_clobber (access->type);
- gimple *stmt = gimple_build_assign (rep, clobber);
-
- if (insert_after)
- gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
- else
- gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
- update_stmt (stmt);
- gimple_set_location (stmt, loc);
- }
-
- for (child = access->first_child; child; child = child->next_sibling)
- clobber_subtree (child, gsi, insert_after, loc);
-}
-
-/* Search for an access representative for the given expression EXPR and
- return it or NULL if it cannot be found. */
-
-static struct access *
-get_access_for_expr (tree expr)
-{
- poly_int64 poffset, psize, pmax_size;
- HOST_WIDE_INT offset, max_size;
- tree base;
- bool reverse;
-
- /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
- a different size than the size of its argument and we need the latter
- one. */
- if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
- expr = TREE_OPERAND (expr, 0);
-
- base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size,
- &reverse);
- if (!known_size_p (pmax_size)
- || !pmax_size.is_constant (&max_size)
- || !poffset.is_constant (&offset)
- || !DECL_P (base))
- return NULL;
-
- if (tree basesize = DECL_SIZE (base))
- {
- poly_int64 sz;
- if (offset < 0
- || !poly_int_tree_p (basesize, &sz)
- || known_le (sz, offset))
- return NULL;
- }
-
- if (max_size == 0
- || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
- return NULL;
-
- return get_var_base_offset_size_access (base, offset, max_size);
-}
-
-/* Replace the expression EXPR with a scalar replacement if there is one and
- generate other statements to do type conversion or subtree copying if
- necessary. GSI is used to place newly created statements, WRITE is true if
- the expression is being written to (it is on a LHS of a statement or output
- in an assembly statement). */
-
-static bool
-sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
-{
- location_t loc;
- struct access *access;
- tree type, bfr, orig_expr;
- bool partial_cplx_access = false;
-
- if (TREE_CODE (*expr) == BIT_FIELD_REF)
- {
- bfr = *expr;
- expr = &TREE_OPERAND (*expr, 0);
- }
- else
- bfr = NULL_TREE;
-
- if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
- {
- expr = &TREE_OPERAND (*expr, 0);
- partial_cplx_access = true;
- }
- access = get_access_for_expr (*expr);
- if (!access)
- return false;
- type = TREE_TYPE (*expr);
- orig_expr = *expr;
-
- loc = gimple_location (gsi_stmt (*gsi));
- gimple_stmt_iterator alt_gsi = gsi_none ();
- if (write && stmt_ends_bb_p (gsi_stmt (*gsi)))
- {
- alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
- gsi = &alt_gsi;
- }
-
- if (access->grp_to_be_replaced)
- {
- tree repl = get_access_replacement (access);
- /* If we replace a non-register typed access simply use the original
- access expression to extract the scalar component afterwards.
- This happens if scalarizing a function return value or parameter
- like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
- gcc.c-torture/compile/20011217-1.c.
-
- We also want to use this when accessing a complex or vector which can
- be accessed as a different type too, potentially creating a need for
- type conversion (see PR42196) and when scalarized unions are involved
- in assembler statements (see PR42398). */
- if (!bfr && !useless_type_conversion_p (type, access->type))
- {
- tree ref;
-
- ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
-
- if (partial_cplx_access)
- {
- /* VIEW_CONVERT_EXPRs in partial complex access are always fine in
- the case of a write because in such case the replacement cannot
- be a gimple register. In the case of a load, we have to
- differentiate in between a register an non-register
- replacement. */
- tree t = build1 (VIEW_CONVERT_EXPR, type, repl);
- gcc_checking_assert (!write || access->grp_partial_lhs);
- if (!access->grp_partial_lhs)
- {
- tree tmp = make_ssa_name (type);
- gassign *stmt = gimple_build_assign (tmp, t);
- /* This is always a read. */
- gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
- t = tmp;
- }
- *expr = t;
- }
- else if (write)
- {
- gassign *stmt;
-
- if (access->grp_partial_lhs)
- ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
- false, GSI_NEW_STMT);
- stmt = gimple_build_assign (repl, ref);
- gimple_set_location (stmt, loc);
- gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
- }
- else
- {
- gassign *stmt;
-
- if (access->grp_partial_lhs)
- repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
- true, GSI_SAME_STMT);
- stmt = gimple_build_assign (ref, repl);
- gimple_set_location (stmt, loc);
- gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
- }
- }
- else
- *expr = repl;
- sra_stats.exprs++;
- }
- else if (write && access->grp_to_be_debug_replaced)
- {
- gdebug *ds = gimple_build_debug_bind (get_access_replacement (access),
- NULL_TREE,
- gsi_stmt (*gsi));
- gsi_insert_after (gsi, ds, GSI_NEW_STMT);
- }
-
- if (access->first_child && !TREE_READONLY (access->base))
- {
- HOST_WIDE_INT start_offset, chunk_size;
- if (bfr
- && tree_fits_uhwi_p (TREE_OPERAND (bfr, 1))
- && tree_fits_uhwi_p (TREE_OPERAND (bfr, 2)))
- {
- chunk_size = tree_to_uhwi (TREE_OPERAND (bfr, 1));
- start_offset = access->offset
- + tree_to_uhwi (TREE_OPERAND (bfr, 2));
- }
- else
- start_offset = chunk_size = 0;
-
- generate_subtree_copies (access->first_child, orig_expr, access->offset,
- start_offset, chunk_size, gsi, write, write,
- loc);
- }
- return true;
-}
-
-/* Where scalar replacements of the RHS have been written to when a replacement
- of a LHS of an assigments cannot be direclty loaded from a replacement of
- the RHS. */
-enum unscalarized_data_handling { SRA_UDH_NONE, /* Nothing done so far. */
- SRA_UDH_RIGHT, /* Data flushed to the RHS. */
- SRA_UDH_LEFT }; /* Data flushed to the LHS. */
-
-struct subreplacement_assignment_data
-{
- /* Offset of the access representing the lhs of the assignment. */
- HOST_WIDE_INT left_offset;
-
- /* LHS and RHS of the original assignment. */
- tree assignment_lhs, assignment_rhs;
-
- /* Access representing the rhs of the whole assignment. */
- struct access *top_racc;
-
- /* Stmt iterator used for statement insertions after the original assignment.
- It points to the main GSI used to traverse a BB during function body
- modification. */
- gimple_stmt_iterator *new_gsi;
-
- /* Stmt iterator used for statement insertions before the original
- assignment. Keeps on pointing to the original statement. */
- gimple_stmt_iterator old_gsi;
-
- /* Location of the assignment. */
- location_t loc;
-
- /* Keeps the information whether we have needed to refresh replacements of
- the LHS and from which side of the assignments this takes place. */
- enum unscalarized_data_handling refreshed;
-};
-
-/* Store all replacements in the access tree rooted in TOP_RACC either to their
- base aggregate if there are unscalarized data or directly to LHS of the
- statement that is pointed to by GSI otherwise. */
-
-static void
-handle_unscalarized_data_in_subtree (struct subreplacement_assignment_data *sad)
-{
- tree src;
- /* If the RHS is a load from a constant, we do not need to (and must not)
- flush replacements to it and can use it directly as if we did. */
- if (TREE_READONLY (sad->top_racc->base))
- {
- sad->refreshed = SRA_UDH_RIGHT;
- return;
- }
- if (sad->top_racc->grp_unscalarized_data)
- {
- src = sad->assignment_rhs;
- sad->refreshed = SRA_UDH_RIGHT;
- }
- else
- {
- src = sad->assignment_lhs;
- sad->refreshed = SRA_UDH_LEFT;
- }
- generate_subtree_copies (sad->top_racc->first_child, src,
- sad->top_racc->offset, 0, 0,
- &sad->old_gsi, false, false, sad->loc);
-}
-
-/* Try to generate statements to load all sub-replacements in an access subtree
- formed by children of LACC from scalar replacements in the SAD->top_racc
- subtree. If that is not possible, refresh the SAD->top_racc base aggregate
- and load the accesses from it. */
-
-static void
-load_assign_lhs_subreplacements (struct access *lacc,
- struct subreplacement_assignment_data *sad)
-{
- for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
- {
- HOST_WIDE_INT offset;
- offset = lacc->offset - sad->left_offset + sad->top_racc->offset;
-
- if (lacc->grp_to_be_replaced)
- {
- struct access *racc;
- gassign *stmt;
- tree rhs;
-
- racc = find_access_in_subtree (sad->top_racc, offset, lacc->size);
- if (racc && racc->grp_to_be_replaced)
- {
- rhs = get_access_replacement (racc);
- if (!useless_type_conversion_p (lacc->type, racc->type))
- rhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
- lacc->type, rhs);
-
- if (racc->grp_partial_lhs && lacc->grp_partial_lhs)
- rhs = force_gimple_operand_gsi (&sad->old_gsi, rhs, true,
- NULL_TREE, true, GSI_SAME_STMT);
- }
- else
- {
- /* No suitable access on the right hand side, need to load from
- the aggregate. See if we have to update it first... */
- if (sad->refreshed == SRA_UDH_NONE)
- handle_unscalarized_data_in_subtree (sad);
-
- if (sad->refreshed == SRA_UDH_LEFT)
- rhs = build_ref_for_model (sad->loc, sad->assignment_lhs,
- lacc->offset - sad->left_offset,
- lacc, sad->new_gsi, true);
- else
- rhs = build_ref_for_model (sad->loc, sad->assignment_rhs,
- lacc->offset - sad->left_offset,
- lacc, sad->new_gsi, true);
- if (lacc->grp_partial_lhs)
- rhs = force_gimple_operand_gsi (sad->new_gsi,
- rhs, true, NULL_TREE,
- false, GSI_NEW_STMT);
- }
-
- stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
- gsi_insert_after (sad->new_gsi, stmt, GSI_NEW_STMT);
- gimple_set_location (stmt, sad->loc);
- update_stmt (stmt);
- sra_stats.subreplacements++;
- }
- else
- {
- if (sad->refreshed == SRA_UDH_NONE
- && lacc->grp_read && !lacc->grp_covered)
- handle_unscalarized_data_in_subtree (sad);
-
- if (lacc && lacc->grp_to_be_debug_replaced)
- {
- gdebug *ds;
- tree drhs;
- struct access *racc = find_access_in_subtree (sad->top_racc,
- offset,
- lacc->size);
-
- if (racc && racc->grp_to_be_replaced)
- {
- if (racc->grp_write || constant_decl_p (racc->base))
- drhs = get_access_replacement (racc);
- else
- drhs = NULL;
- }
- else if (sad->refreshed == SRA_UDH_LEFT)
- drhs = build_debug_ref_for_model (sad->loc, lacc->base,
- lacc->offset, lacc);
- else if (sad->refreshed == SRA_UDH_RIGHT)
- drhs = build_debug_ref_for_model (sad->loc, sad->top_racc->base,
- offset, lacc);
- else
- drhs = NULL_TREE;
- if (drhs
- && !useless_type_conversion_p (lacc->type, TREE_TYPE (drhs)))
- drhs = fold_build1_loc (sad->loc, VIEW_CONVERT_EXPR,
- lacc->type, drhs);
- ds = gimple_build_debug_bind (get_access_replacement (lacc),
- drhs, gsi_stmt (sad->old_gsi));
- gsi_insert_after (sad->new_gsi, ds, GSI_NEW_STMT);
- }
- }
-
- if (lacc->first_child)
- load_assign_lhs_subreplacements (lacc, sad);
- }
-}
-
-/* Result code for SRA assignment modification. */
-enum assignment_mod_result { SRA_AM_NONE, /* nothing done for the stmt */
- SRA_AM_MODIFIED, /* stmt changed but not
- removed */
- SRA_AM_REMOVED }; /* stmt eliminated */
-
-/* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
- to the assignment and GSI is the statement iterator pointing at it. Returns
- the same values as sra_modify_assign. */
-
-static enum assignment_mod_result
-sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
-{
- tree lhs = gimple_assign_lhs (stmt);
- struct access *acc = get_access_for_expr (lhs);
- if (!acc)
- return SRA_AM_NONE;
- location_t loc = gimple_location (stmt);
-
- if (gimple_clobber_p (stmt))
- {
- /* Clobber the replacement variable. */
- clobber_subtree (acc, gsi, !acc->grp_covered, loc);
- /* Remove clobbers of fully scalarized variables, they are dead. */
- if (acc->grp_covered)
- {
- unlink_stmt_vdef (stmt);
- gsi_remove (gsi, true);
- release_defs (stmt);
- return SRA_AM_REMOVED;
- }
- else
- return SRA_AM_MODIFIED;
- }
-
- if (CONSTRUCTOR_NELTS (gimple_assign_rhs1 (stmt)) > 0)
- {
- /* I have never seen this code path trigger but if it can happen the
- following should handle it gracefully. */
- if (access_has_children_p (acc))
- generate_subtree_copies (acc->first_child, lhs, acc->offset, 0, 0, gsi,
- true, true, loc);
- return SRA_AM_MODIFIED;
- }
-
- if (acc->grp_covered)
- {
- init_subtree_with_zero (acc, gsi, false, loc);
- unlink_stmt_vdef (stmt);
- gsi_remove (gsi, true);
- release_defs (stmt);
- return SRA_AM_REMOVED;
- }
- else
- {
- init_subtree_with_zero (acc, gsi, true, loc);
- return SRA_AM_MODIFIED;
- }
-}
-
-/* Create and return a new suitable default definition SSA_NAME for RACC which
- is an access describing an uninitialized part of an aggregate that is being
- loaded. REG_TREE is used instead of the actual RACC type if that is not of
- a gimple register type. */
-
-static tree
-get_repl_default_def_ssa_name (struct access *racc, tree reg_type)
-{
- gcc_checking_assert (!racc->grp_to_be_replaced
- && !racc->grp_to_be_debug_replaced);
- if (!racc->replacement_decl)
- racc->replacement_decl = create_access_replacement (racc, reg_type);
- return get_or_create_ssa_default_def (cfun, racc->replacement_decl);
-}
-
-
-/* Generate statements to call .DEFERRED_INIT to initialize scalar replacements
- of accesses within a subtree ACCESS; all its children, siblings and their
- children are to be processed.
- GSI is a statement iterator used to place the new statements. */
-static void
-generate_subtree_deferred_init (struct access *access,
- tree init_type,
- tree decl_name,
- gimple_stmt_iterator *gsi,
- location_t loc)
-{
- do
- {
- if (access->grp_to_be_replaced)
- {
- tree repl = get_access_replacement (access);
- gimple *call
- = gimple_build_call_internal (IFN_DEFERRED_INIT, 3,
- TYPE_SIZE_UNIT (TREE_TYPE (repl)),
- init_type, decl_name);
- gimple_call_set_lhs (call, repl);
- gsi_insert_before (gsi, call, GSI_SAME_STMT);
- update_stmt (call);
- gimple_set_location (call, loc);
- sra_stats.subtree_deferred_init++;
- }
- if (access->first_child)
- generate_subtree_deferred_init (access->first_child, init_type,
- decl_name, gsi, loc);
-
- access = access ->next_sibling;
- }
- while (access);
-}
-
-/* For a call to .DEFERRED_INIT:
- var = .DEFERRED_INIT (size_of_var, init_type, name_of_var);
- examine the LHS variable VAR and replace it with a scalar replacement if
- there is one, also replace the RHS call to a call to .DEFERRED_INIT of
- the corresponding scalar relacement variable. Examine the subtree and
- do the scalar replacements in the subtree too. STMT is the call, GSI is
- the statment iterator to place newly created statement. */
-
-static enum assignment_mod_result
-sra_modify_deferred_init (gimple *stmt, gimple_stmt_iterator *gsi)
-{
- tree lhs = gimple_call_lhs (stmt);
- tree init_type = gimple_call_arg (stmt, 1);
- tree decl_name = gimple_call_arg (stmt, 2);
-
- struct access *lhs_access = get_access_for_expr (lhs);
- if (!lhs_access)
- return SRA_AM_NONE;
-
- location_t loc = gimple_location (stmt);
-
- if (lhs_access->grp_to_be_replaced)
- {
- tree lhs_repl = get_access_replacement (lhs_access);
- gimple_call_set_lhs (stmt, lhs_repl);
- tree arg0_repl = TYPE_SIZE_UNIT (TREE_TYPE (lhs_repl));
- gimple_call_set_arg (stmt, 0, arg0_repl);
- sra_stats.deferred_init++;
- gcc_assert (!lhs_access->first_child);
- return SRA_AM_MODIFIED;
- }
-
- if (lhs_access->first_child)
- generate_subtree_deferred_init (lhs_access->first_child,
- init_type, decl_name, gsi, loc);
- if (lhs_access->grp_covered)
- {
- unlink_stmt_vdef (stmt);
- gsi_remove (gsi, true);
- release_defs (stmt);
- return SRA_AM_REMOVED;
- }
-
- return SRA_AM_MODIFIED;
-}
-
-/* Examine both sides of the assignment statement pointed to by STMT, replace
- them with a scalare replacement if there is one and generate copying of
- replacements if scalarized aggregates have been used in the assignment. GSI
- is used to hold generated statements for type conversions and subtree
- copying. */
-
-static enum assignment_mod_result
-sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
-{
- struct access *lacc, *racc;
- tree lhs, rhs;
- bool modify_this_stmt = false;
- bool force_gimple_rhs = false;
- location_t loc;
- gimple_stmt_iterator orig_gsi = *gsi;
-
- if (!gimple_assign_single_p (stmt))
- return SRA_AM_NONE;
- lhs = gimple_assign_lhs (stmt);
- rhs = gimple_assign_rhs1 (stmt);
-
- if (TREE_CODE (rhs) == CONSTRUCTOR)
- return sra_modify_constructor_assign (stmt, gsi);
-
- if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
- || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
- || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
- {
- modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (stmt),
- gsi, false);
- modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (stmt),
- gsi, true);
- return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
- }
-
- lacc = get_access_for_expr (lhs);
- racc = get_access_for_expr (rhs);
- if (!lacc && !racc)
- return SRA_AM_NONE;
- /* Avoid modifying initializations of constant-pool replacements. */
- if (racc && (racc->replacement_decl == lhs))
- return SRA_AM_NONE;
-
- loc = gimple_location (stmt);
- if (lacc && lacc->grp_to_be_replaced)
- {
- lhs = get_access_replacement (lacc);
- gimple_assign_set_lhs (stmt, lhs);
- modify_this_stmt = true;
- if (lacc->grp_partial_lhs)
- force_gimple_rhs = true;
- sra_stats.exprs++;
- }
-
- if (racc && racc->grp_to_be_replaced)
- {
- rhs = get_access_replacement (racc);
- modify_this_stmt = true;
- if (racc->grp_partial_lhs)
- force_gimple_rhs = true;
- sra_stats.exprs++;
- }
- else if (racc
- && !racc->grp_unscalarized_data
- && !racc->grp_unscalarizable_region
- && TREE_CODE (lhs) == SSA_NAME
- && !access_has_replacements_p (racc))
- {
- rhs = get_repl_default_def_ssa_name (racc, TREE_TYPE (lhs));
- modify_this_stmt = true;
- sra_stats.exprs++;
- }
-
- if (modify_this_stmt)
- {
- if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
- {
- /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
- ??? This should move to fold_stmt which we simply should
- call after building a VIEW_CONVERT_EXPR here. */
- if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
- && !contains_bitfld_component_ref_p (lhs))
- {
- lhs = build_ref_for_model (loc, lhs, 0, racc, gsi, false);
- gimple_assign_set_lhs (stmt, lhs);
- }
- else if (lacc
- && AGGREGATE_TYPE_P (TREE_TYPE (rhs))
- && !contains_vce_or_bfcref_p (rhs))
- rhs = build_ref_for_model (loc, rhs, 0, lacc, gsi, false);
-
- if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
- {
- rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
- rhs);
- if (is_gimple_reg_type (TREE_TYPE (lhs))
- && TREE_CODE (lhs) != SSA_NAME)
- force_gimple_rhs = true;
- }
- }
- }
-
- if (lacc && lacc->grp_to_be_debug_replaced)
- {
- tree dlhs = get_access_replacement (lacc);
- tree drhs = unshare_expr (rhs);
- if (!useless_type_conversion_p (TREE_TYPE (dlhs), TREE_TYPE (drhs)))
- {
- if (AGGREGATE_TYPE_P (TREE_TYPE (drhs))
- && !contains_vce_or_bfcref_p (drhs))
- drhs = build_debug_ref_for_model (loc, drhs, 0, lacc);
- if (drhs
- && !useless_type_conversion_p (TREE_TYPE (dlhs),
- TREE_TYPE (drhs)))
- drhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
- TREE_TYPE (dlhs), drhs);
- }
- gdebug *ds = gimple_build_debug_bind (dlhs, drhs, stmt);
- gsi_insert_before (gsi, ds, GSI_SAME_STMT);
- }
-
- /* From this point on, the function deals with assignments in between
- aggregates when at least one has scalar reductions of some of its
- components. There are three possible scenarios: Both the LHS and RHS have
- to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
-
- In the first case, we would like to load the LHS components from RHS
- components whenever possible. If that is not possible, we would like to
- read it directly from the RHS (after updating it by storing in it its own
- components). If there are some necessary unscalarized data in the LHS,
- those will be loaded by the original assignment too. If neither of these
- cases happen, the original statement can be removed. Most of this is done
- by load_assign_lhs_subreplacements.
-
- In the second case, we would like to store all RHS scalarized components
- directly into LHS and if they cover the aggregate completely, remove the
- statement too. In the third case, we want the LHS components to be loaded
- directly from the RHS (DSE will remove the original statement if it
- becomes redundant).
-
- This is a bit complex but manageable when types match and when unions do
- not cause confusion in a way that we cannot really load a component of LHS
- from the RHS or vice versa (the access representing this level can have
- subaccesses that are accessible only through a different union field at a
- higher level - different from the one used in the examined expression).
- Unions are fun.
-
- Therefore, I specially handle a fourth case, happening when there is a
- specific type cast or it is impossible to locate a scalarized subaccess on
- the other side of the expression. If that happens, I simply "refresh" the
- RHS by storing in it is scalarized components leave the original statement
- there to do the copying and then load the scalar replacements of the LHS.
- This is what the first branch does. */
-
- if (modify_this_stmt
- || gimple_has_volatile_ops (stmt)
- || contains_vce_or_bfcref_p (rhs)
- || contains_vce_or_bfcref_p (lhs)
- || stmt_ends_bb_p (stmt))
- {
- /* No need to copy into a constant, it comes pre-initialized. */
- if (access_has_children_p (racc) && !TREE_READONLY (racc->base))
- generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
- gsi, false, false, loc);
- if (access_has_children_p (lacc))
- {
- gimple_stmt_iterator alt_gsi = gsi_none ();
- if (stmt_ends_bb_p (stmt))
- {
- alt_gsi = gsi_start_edge (single_non_eh_succ (gsi_bb (*gsi)));
- gsi = &alt_gsi;
- }
- generate_subtree_copies (lacc->first_child, lhs, lacc->offset, 0, 0,
- gsi, true, true, loc);
- }
- sra_stats.separate_lhs_rhs_handling++;
-
- /* This gimplification must be done after generate_subtree_copies,
- lest we insert the subtree copies in the middle of the gimplified
- sequence. */
- if (force_gimple_rhs)
- rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
- true, GSI_SAME_STMT);
- if (gimple_assign_rhs1 (stmt) != rhs)
- {
- modify_this_stmt = true;
- gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
- gcc_assert (stmt == gsi_stmt (orig_gsi));
- }
-
- return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
- }
- else
- {
- if (access_has_children_p (lacc)
- && access_has_children_p (racc)
- /* When an access represents an unscalarizable region, it usually
- represents accesses with variable offset and thus must not be used
- to generate new memory accesses. */
- && !lacc->grp_unscalarizable_region
- && !racc->grp_unscalarizable_region)
- {
- struct subreplacement_assignment_data sad;
-
- sad.left_offset = lacc->offset;
- sad.assignment_lhs = lhs;
- sad.assignment_rhs = rhs;
- sad.top_racc = racc;
- sad.old_gsi = *gsi;
- sad.new_gsi = gsi;
- sad.loc = gimple_location (stmt);
- sad.refreshed = SRA_UDH_NONE;
-
- if (lacc->grp_read && !lacc->grp_covered)
- handle_unscalarized_data_in_subtree (&sad);
-
- load_assign_lhs_subreplacements (lacc, &sad);
- if (sad.refreshed != SRA_UDH_RIGHT)
- {
- gsi_next (gsi);
- unlink_stmt_vdef (stmt);
- gsi_remove (&sad.old_gsi, true);
- release_defs (stmt);
- sra_stats.deleted++;
- return SRA_AM_REMOVED;
- }
- }
- else
- {
- if (access_has_children_p (racc)
- && !racc->grp_unscalarized_data
- && TREE_CODE (lhs) != SSA_NAME)
- {
- if (dump_file)
- {
- fprintf (dump_file, "Removing load: ");
- print_gimple_stmt (dump_file, stmt, 0);
- }
- generate_subtree_copies (racc->first_child, lhs,
- racc->offset, 0, 0, gsi,
- false, false, loc);
- gcc_assert (stmt == gsi_stmt (*gsi));
- unlink_stmt_vdef (stmt);
- gsi_remove (gsi, true);
- release_defs (stmt);
- sra_stats.deleted++;
- return SRA_AM_REMOVED;
- }
- /* Restore the aggregate RHS from its components so the
- prevailing aggregate copy does the right thing. */
- if (access_has_children_p (racc) && !TREE_READONLY (racc->base))
- generate_subtree_copies (racc->first_child, rhs, racc->offset, 0, 0,
- gsi, false, false, loc);
- /* Re-load the components of the aggregate copy destination.
- But use the RHS aggregate to load from to expose more
- optimization opportunities. */
- if (access_has_children_p (lacc))
- generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
- 0, 0, gsi, true, true, loc);
- }
-
- return SRA_AM_NONE;
- }
-}
-
-/* Set any scalar replacements of values in the constant pool to the initial
- value of the constant. (Constant-pool decls like *.LC0 have effectively
- been initialized before the program starts, we must do the same for their
- replacements.) Thus, we output statements like 'SR.1 = *.LC0[0];' into
- the function's entry block. */
-
-static void
-initialize_constant_pool_replacements (void)
-{
- gimple_seq seq = NULL;
- gimple_stmt_iterator gsi = gsi_start (seq);
- bitmap_iterator bi;
- unsigned i;
-
- EXECUTE_IF_SET_IN_BITMAP (candidate_bitmap, 0, i, bi)
- {
- tree var = candidate (i);
- if (!constant_decl_p (var))
- continue;
-
- struct access *access = get_first_repr_for_decl (var);
-
- while (access)
- {
- if (access->replacement_decl)
- {
- gassign *stmt
- = gimple_build_assign (get_access_replacement (access),
- unshare_expr (access->expr));
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Generating constant initializer: ");
- print_gimple_stmt (dump_file, stmt, 0);
- fprintf (dump_file, "\n");
- }
- gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
- update_stmt (stmt);
- }
-
- if (access->first_child)
- access = access->first_child;
- else if (access->next_sibling)
- access = access->next_sibling;
- else
- {
- while (access->parent && !access->next_sibling)
- access = access->parent;
- if (access->next_sibling)
- access = access->next_sibling;
- else
- access = access->next_grp;
- }
- }
- }
-
- seq = gsi_seq (gsi);
- if (seq)
- gsi_insert_seq_on_edge_immediate (
- single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
-}
-
-/* Traverse the function body and all modifications as decided in
- analyze_all_variable_accesses. Return true iff the CFG has been
- changed. */
-
-static bool
-sra_modify_function_body (void)
-{
- bool cfg_changed = false;
- basic_block bb;
-
- initialize_constant_pool_replacements ();
-
- FOR_EACH_BB_FN (bb, cfun)
- {
- gimple_stmt_iterator gsi = gsi_start_bb (bb);
- while (!gsi_end_p (gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- enum assignment_mod_result assign_result;
- bool modified = false, deleted = false;
- tree *t;
- unsigned i;
-
- switch (gimple_code (stmt))
- {
- case GIMPLE_RETURN:
- t = gimple_return_retval_ptr (as_a <greturn *> (stmt));
- if (*t != NULL_TREE)
- modified |= sra_modify_expr (t, &gsi, false);
- break;
-
- case GIMPLE_ASSIGN:
- assign_result = sra_modify_assign (stmt, &gsi);
- modified |= assign_result == SRA_AM_MODIFIED;
- deleted = assign_result == SRA_AM_REMOVED;
- break;
-
- case GIMPLE_CALL:
- /* Handle calls to .DEFERRED_INIT specially. */
- if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
- {
- assign_result = sra_modify_deferred_init (stmt, &gsi);
- modified |= assign_result == SRA_AM_MODIFIED;
- deleted = assign_result == SRA_AM_REMOVED;
- }
- else
- {
- /* Operands must be processed before the lhs. */
- for (i = 0; i < gimple_call_num_args (stmt); i++)
- {
- t = gimple_call_arg_ptr (stmt, i);
- modified |= sra_modify_expr (t, &gsi, false);
- }
-
- if (gimple_call_lhs (stmt))
- {
- t = gimple_call_lhs_ptr (stmt);
- modified |= sra_modify_expr (t, &gsi, true);
- }
- }
- break;
-
- case GIMPLE_ASM:
- {
- gasm *asm_stmt = as_a <gasm *> (stmt);
- for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
- {
- t = &TREE_VALUE (gimple_asm_input_op (asm_stmt, i));
- modified |= sra_modify_expr (t, &gsi, false);
- }
- for (i = 0; i < gimple_asm_noutputs (asm_stmt); i++)
- {
- t = &TREE_VALUE (gimple_asm_output_op (asm_stmt, i));
- modified |= sra_modify_expr (t, &gsi, true);
- }
- }
- break;
-
- default:
- break;
- }
-
- if (modified)
- {
- update_stmt (stmt);
- if (maybe_clean_eh_stmt (stmt)
- && gimple_purge_dead_eh_edges (gimple_bb (stmt)))
- cfg_changed = true;
- }
- if (!deleted)
- gsi_next (&gsi);
- }
- }
-
- gsi_commit_edge_inserts ();
- return cfg_changed;
-}
-
-/* Generate statements initializing scalar replacements of parts of function
- parameters. */
-
-static void
-initialize_parameter_reductions (void)
-{
- gimple_stmt_iterator gsi;
- gimple_seq seq = NULL;
- tree parm;
-
- gsi = gsi_start (seq);
- for (parm = DECL_ARGUMENTS (current_function_decl);
- parm;
- parm = DECL_CHAIN (parm))
- {
- vec<access_p> *access_vec;
- struct access *access;
-
- if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
- continue;
- access_vec = get_base_access_vector (parm);
- if (!access_vec)
- continue;
-
- for (access = (*access_vec)[0];
- access;
- access = access->next_grp)
- generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true,
- EXPR_LOCATION (parm));
- }
-
- seq = gsi_seq (gsi);
- if (seq)
- gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
-}
-
-/* The "main" function of intraprocedural SRA passes. Runs the analysis and if
- it reveals there are components of some aggregates to be scalarized, it runs
- the required transformations. */
-static unsigned int
-perform_intra_sra (void)
-{
- int ret = 0;
- sra_initialize ();
-
- if (!find_var_candidates ())
- goto out;
-
- if (!scan_function ())
- goto out;
-
- if (!analyze_all_variable_accesses ())
- goto out;
-
- if (sra_modify_function_body ())
- ret = TODO_update_ssa | TODO_cleanup_cfg;
- else
- ret = TODO_update_ssa;
- initialize_parameter_reductions ();
-
- statistics_counter_event (cfun, "Scalar replacements created",
- sra_stats.replacements);
- statistics_counter_event (cfun, "Modified expressions", sra_stats.exprs);
- statistics_counter_event (cfun, "Subtree copy stmts",
- sra_stats.subtree_copies);
- statistics_counter_event (cfun, "Subreplacement stmts",
- sra_stats.subreplacements);
- statistics_counter_event (cfun, "Deleted stmts", sra_stats.deleted);
- statistics_counter_event (cfun, "Separate LHS and RHS handling",
- sra_stats.separate_lhs_rhs_handling);
-
- out:
- sra_deinitialize ();
- return ret;
-}
-
-/* Perform early intraprocedural SRA. */
-static unsigned int
-early_intra_sra (void)
-{
- sra_mode = SRA_MODE_EARLY_INTRA;
- return perform_intra_sra ();
-}
-
-/* Perform "late" intraprocedural SRA. */
-static unsigned int
-late_intra_sra (void)
-{
- sra_mode = SRA_MODE_INTRA;
- return perform_intra_sra ();
-}
-
-
-static bool
-gate_intra_sra (void)
-{
- return flag_tree_sra != 0 && dbg_cnt (tree_sra);
-}
-
-
-namespace {
-
-const pass_data pass_data_sra_early =
-{
- GIMPLE_PASS, /* type */
- "esra", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- TV_TREE_SRA, /* tv_id */
- ( PROP_cfg | PROP_ssa ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_update_ssa, /* todo_flags_finish */
-};
-
-class pass_sra_early : public gimple_opt_pass
-{
-public:
- pass_sra_early (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_sra_early, ctxt)
- {}
-
- /* opt_pass methods: */
- virtual bool gate (function *) { return gate_intra_sra (); }
- virtual unsigned int execute (function *) { return early_intra_sra (); }
-
-}; // class pass_sra_early
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_sra_early (gcc::context *ctxt)
-{
- return new pass_sra_early (ctxt);
-}
-
-namespace {
-
-const pass_data pass_data_sra =
-{
- GIMPLE_PASS, /* type */
- "sra", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- TV_TREE_SRA, /* tv_id */
- ( PROP_cfg | PROP_ssa ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- TODO_update_address_taken, /* todo_flags_start */
- TODO_update_ssa, /* todo_flags_finish */
-};
-
-class pass_sra : public gimple_opt_pass
-{
-public:
- pass_sra (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_sra, ctxt)
- {}
-
- /* opt_pass methods: */
- virtual bool gate (function *) { return gate_intra_sra (); }
- virtual unsigned int execute (function *) { return late_intra_sra (); }
-
-}; // class pass_sra
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_sra (gcc::context *ctxt)
-{
- return new pass_sra (ctxt);
-}