aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-phiopt.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-ssa-phiopt.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-ssa-phiopt.c')
-rw-r--r--gcc/tree-ssa-phiopt.c3854
1 files changed, 0 insertions, 3854 deletions
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
deleted file mode 100644
index 562468b..0000000
--- a/gcc/tree-ssa-phiopt.c
+++ /dev/null
@@ -1,3854 +0,0 @@
-/* Optimization of PHI nodes by converting them into straightline code.
- Copyright (C) 2004-2022 Free Software Foundation, Inc.
-
-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/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "backend.h"
-#include "insn-codes.h"
-#include "rtl.h"
-#include "tree.h"
-#include "gimple.h"
-#include "cfghooks.h"
-#include "tree-pass.h"
-#include "ssa.h"
-#include "tree-ssa.h"
-#include "optabs-tree.h"
-#include "insn-config.h"
-#include "gimple-pretty-print.h"
-#include "fold-const.h"
-#include "stor-layout.h"
-#include "cfganal.h"
-#include "gimplify.h"
-#include "gimple-iterator.h"
-#include "gimplify-me.h"
-#include "tree-cfg.h"
-#include "tree-dfa.h"
-#include "domwalk.h"
-#include "cfgloop.h"
-#include "tree-data-ref.h"
-#include "tree-scalar-evolution.h"
-#include "tree-inline.h"
-#include "case-cfn-macros.h"
-#include "tree-eh.h"
-#include "gimple-fold.h"
-#include "internal-fn.h"
-#include "gimple-range.h"
-#include "gimple-match.h"
-#include "dbgcnt.h"
-
-static unsigned int tree_ssa_phiopt_worker (bool, bool, bool);
-static bool two_value_replacement (basic_block, basic_block, edge, gphi *,
- tree, tree);
-static bool match_simplify_replacement (basic_block, basic_block,
- edge, edge, gphi *, tree, tree, bool);
-static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree,
- gimple *);
-static int value_replacement (basic_block, basic_block,
- edge, edge, gphi *, tree, tree);
-static bool minmax_replacement (basic_block, basic_block,
- edge, edge, gphi *, tree, tree);
-static bool spaceship_replacement (basic_block, basic_block,
- edge, edge, gphi *, tree, tree);
-static bool cond_removal_in_builtin_zero_pattern (basic_block, basic_block,
- edge, edge, gphi *,
- tree, tree);
-static bool cond_store_replacement (basic_block, basic_block, edge, edge,
- hash_set<tree> *);
-static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
-static hash_set<tree> * get_non_trapping ();
-static void replace_phi_edge_with_variable (basic_block, edge, gphi *, tree);
-static void hoist_adjacent_loads (basic_block, basic_block,
- basic_block, basic_block);
-static bool gate_hoist_loads (void);
-
-/* This pass tries to transform conditional stores into unconditional
- ones, enabling further simplifications with the simpler then and else
- blocks. In particular it replaces this:
-
- bb0:
- if (cond) goto bb2; else goto bb1;
- bb1:
- *p = RHS;
- bb2:
-
- with
-
- bb0:
- if (cond) goto bb1; else goto bb2;
- bb1:
- condtmp' = *p;
- bb2:
- condtmp = PHI <RHS, condtmp'>
- *p = condtmp;
-
- This transformation can only be done under several constraints,
- documented below. It also replaces:
-
- bb0:
- if (cond) goto bb2; else goto bb1;
- bb1:
- *p = RHS1;
- goto bb3;
- bb2:
- *p = RHS2;
- bb3:
-
- with
-
- bb0:
- if (cond) goto bb3; else goto bb1;
- bb1:
- bb3:
- condtmp = PHI <RHS1, RHS2>
- *p = condtmp; */
-
-static unsigned int
-tree_ssa_cs_elim (void)
-{
- unsigned todo;
- /* ??? We are not interested in loop related info, but the following
- will create it, ICEing as we didn't init loops with pre-headers.
- An interfacing issue of find_data_references_in_bb. */
- loop_optimizer_init (LOOPS_NORMAL);
- scev_initialize ();
- todo = tree_ssa_phiopt_worker (true, false, false);
- scev_finalize ();
- loop_optimizer_finalize ();
- return todo;
-}
-
-/* Return the singleton PHI in the SEQ of PHIs for edges E0 and E1. */
-
-static gphi *
-single_non_singleton_phi_for_edges (gimple_seq seq, edge e0, edge e1)
-{
- gimple_stmt_iterator i;
- gphi *phi = NULL;
- if (gimple_seq_singleton_p (seq))
- return as_a <gphi *> (gsi_stmt (gsi_start (seq)));
- for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
- {
- gphi *p = as_a <gphi *> (gsi_stmt (i));
- /* If the PHI arguments are equal then we can skip this PHI. */
- if (operand_equal_for_phi_arg_p (gimple_phi_arg_def (p, e0->dest_idx),
- gimple_phi_arg_def (p, e1->dest_idx)))
- continue;
-
- /* If we already have a PHI that has the two edge arguments are
- different, then return it is not a singleton for these PHIs. */
- if (phi)
- return NULL;
-
- phi = p;
- }
- return phi;
-}
-
-/* The core routine of conditional store replacement and normal
- phi optimizations. Both share much of the infrastructure in how
- to match applicable basic block patterns. DO_STORE_ELIM is true
- when we want to do conditional store replacement, false otherwise.
- DO_HOIST_LOADS is true when we want to hoist adjacent loads out
- of diamond control flow patterns, false otherwise. */
-static unsigned int
-tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
-{
- basic_block bb;
- basic_block *bb_order;
- unsigned n, i;
- bool cfgchanged = false;
- hash_set<tree> *nontrap = 0;
-
- calculate_dominance_info (CDI_DOMINATORS);
-
- if (do_store_elim)
- /* Calculate the set of non-trapping memory accesses. */
- nontrap = get_non_trapping ();
-
- /* Search every basic block for COND_EXPR we may be able to optimize.
-
- We walk the blocks in order that guarantees that a block with
- a single predecessor is processed before the predecessor.
- This ensures that we collapse inner ifs before visiting the
- outer ones, and also that we do not try to visit a removed
- block. */
- bb_order = single_pred_before_succ_order ();
- n = n_basic_blocks_for_fn (cfun) - NUM_FIXED_BLOCKS;
-
- for (i = 0; i < n; i++)
- {
- gimple *cond_stmt;
- gphi *phi;
- basic_block bb1, bb2;
- edge e1, e2;
- tree arg0, arg1;
-
- bb = bb_order[i];
-
- cond_stmt = last_stmt (bb);
- /* Check to see if the last statement is a GIMPLE_COND. */
- if (!cond_stmt
- || gimple_code (cond_stmt) != GIMPLE_COND)
- continue;
-
- e1 = EDGE_SUCC (bb, 0);
- bb1 = e1->dest;
- e2 = EDGE_SUCC (bb, 1);
- bb2 = e2->dest;
-
- /* We cannot do the optimization on abnormal edges. */
- if ((e1->flags & EDGE_ABNORMAL) != 0
- || (e2->flags & EDGE_ABNORMAL) != 0)
- continue;
-
- /* If either bb1's succ or bb2 or bb2's succ is non NULL. */
- if (EDGE_COUNT (bb1->succs) == 0
- || EDGE_COUNT (bb2->succs) == 0)
- continue;
-
- /* Find the bb which is the fall through to the other. */
- if (EDGE_SUCC (bb1, 0)->dest == bb2)
- ;
- else if (EDGE_SUCC (bb2, 0)->dest == bb1)
- {
- std::swap (bb1, bb2);
- std::swap (e1, e2);
- }
- else if (do_store_elim
- && EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest)
- {
- basic_block bb3 = EDGE_SUCC (bb1, 0)->dest;
-
- if (!single_succ_p (bb1)
- || (EDGE_SUCC (bb1, 0)->flags & EDGE_FALLTHRU) == 0
- || !single_succ_p (bb2)
- || (EDGE_SUCC (bb2, 0)->flags & EDGE_FALLTHRU) == 0
- || EDGE_COUNT (bb3->preds) != 2)
- continue;
- if (cond_if_else_store_replacement (bb1, bb2, bb3))
- cfgchanged = true;
- continue;
- }
- else if (do_hoist_loads
- && EDGE_SUCC (bb1, 0)->dest == EDGE_SUCC (bb2, 0)->dest)
- {
- basic_block bb3 = EDGE_SUCC (bb1, 0)->dest;
-
- if (!FLOAT_TYPE_P (TREE_TYPE (gimple_cond_lhs (cond_stmt)))
- && single_succ_p (bb1)
- && single_succ_p (bb2)
- && single_pred_p (bb1)
- && single_pred_p (bb2)
- && EDGE_COUNT (bb->succs) == 2
- && EDGE_COUNT (bb3->preds) == 2
- /* If one edge or the other is dominant, a conditional move
- is likely to perform worse than the well-predicted branch. */
- && !predictable_edge_p (EDGE_SUCC (bb, 0))
- && !predictable_edge_p (EDGE_SUCC (bb, 1)))
- hoist_adjacent_loads (bb, bb1, bb2, bb3);
- continue;
- }
- else
- continue;
-
- e1 = EDGE_SUCC (bb1, 0);
-
- /* Make sure that bb1 is just a fall through. */
- if (!single_succ_p (bb1)
- || (e1->flags & EDGE_FALLTHRU) == 0)
- continue;
-
- if (do_store_elim)
- {
- /* Also make sure that bb1 only have one predecessor and that it
- is bb. */
- if (!single_pred_p (bb1)
- || single_pred (bb1) != bb)
- continue;
-
- /* bb1 is the middle block, bb2 the join block, bb the split block,
- e1 the fallthrough edge from bb1 to bb2. We can't do the
- optimization if the join block has more than two predecessors. */
- if (EDGE_COUNT (bb2->preds) > 2)
- continue;
- if (cond_store_replacement (bb1, bb2, e1, e2, nontrap))
- cfgchanged = true;
- }
- else
- {
- gimple_seq phis = phi_nodes (bb2);
- gimple_stmt_iterator gsi;
- bool candorest = true;
-
- /* Value replacement can work with more than one PHI
- so try that first. */
- if (!early_p)
- for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- phi = as_a <gphi *> (gsi_stmt (gsi));
- arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
- arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
- if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1) == 2)
- {
- candorest = false;
- cfgchanged = true;
- break;
- }
- }
-
- if (!candorest)
- continue;
-
- phi = single_non_singleton_phi_for_edges (phis, e1, e2);
- if (!phi)
- continue;
-
- arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
- arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
-
- /* Something is wrong if we cannot find the arguments in the PHI
- node. */
- gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE);
-
- gphi *newphi;
- if (single_pred_p (bb1)
- && (newphi = factor_out_conditional_conversion (e1, e2, phi,
- arg0, arg1,
- cond_stmt)))
- {
- phi = newphi;
- /* factor_out_conditional_conversion may create a new PHI in
- BB2 and eliminate an existing PHI in BB2. Recompute values
- that may be affected by that change. */
- arg0 = gimple_phi_arg_def (phi, e1->dest_idx);
- arg1 = gimple_phi_arg_def (phi, e2->dest_idx);
- gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE);
- }
-
- /* Do the replacement of conditional if it can be done. */
- if (!early_p && two_value_replacement (bb, bb1, e2, phi, arg0, arg1))
- cfgchanged = true;
- else if (match_simplify_replacement (bb, bb1, e1, e2, phi,
- arg0, arg1,
- early_p))
- cfgchanged = true;
- else if (!early_p
- && single_pred_p (bb1)
- && cond_removal_in_builtin_zero_pattern (bb, bb1, e1, e2,
- phi, arg0, arg1))
- cfgchanged = true;
- else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
- cfgchanged = true;
- else if (single_pred_p (bb1)
- && spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
- cfgchanged = true;
- }
- }
-
- free (bb_order);
-
- if (do_store_elim)
- delete nontrap;
- /* If the CFG has changed, we should cleanup the CFG. */
- if (cfgchanged && do_store_elim)
- {
- /* In cond-store replacement we have added some loads on edges
- and new VOPS (as we moved the store, and created a load). */
- gsi_commit_edge_inserts ();
- return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals;
- }
- else if (cfgchanged)
- return TODO_cleanup_cfg;
- return 0;
-}
-
-/* Replace PHI node element whose edge is E in block BB with variable NEW.
- Remove the edge from COND_BLOCK which does not lead to BB (COND_BLOCK
- is known to have two edges, one of which must reach BB). */
-
-static void
-replace_phi_edge_with_variable (basic_block cond_block,
- edge e, gphi *phi, tree new_tree)
-{
- basic_block bb = gimple_bb (phi);
- gimple_stmt_iterator gsi;
- tree phi_result = PHI_RESULT (phi);
-
- /* Duplicate range info if they are the only things setting the target PHI.
- This is needed as later on, the new_tree will be replacing
- The assignement of the PHI.
- For an example:
- bb1:
- _4 = min<a_1, 255>
- goto bb2
-
- # RANGE [-INF, 255]
- a_3 = PHI<_4(1)>
- bb3:
-
- use(a_3)
- And _4 gets propagated into the use of a_3 and losing the range info.
- This can't be done for more than 2 incoming edges as the propagation
- won't happen.
- The new_tree needs to be defined in the same basic block as the conditional. */
- if (TREE_CODE (new_tree) == SSA_NAME
- && EDGE_COUNT (gimple_bb (phi)->preds) == 2
- && INTEGRAL_TYPE_P (TREE_TYPE (phi_result))
- && !SSA_NAME_RANGE_INFO (new_tree)
- && SSA_NAME_RANGE_INFO (phi_result)
- && gimple_bb (SSA_NAME_DEF_STMT (new_tree)) == cond_block
- && dbg_cnt (phiopt_edge_range))
- duplicate_ssa_name_range_info (new_tree,
- SSA_NAME_RANGE_TYPE (phi_result),
- SSA_NAME_RANGE_INFO (phi_result));
-
- /* Change the PHI argument to new. */
- SET_USE (PHI_ARG_DEF_PTR (phi, e->dest_idx), new_tree);
-
- /* Remove the empty basic block. */
- edge edge_to_remove;
- if (EDGE_SUCC (cond_block, 0)->dest == bb)
- edge_to_remove = EDGE_SUCC (cond_block, 1);
- else
- edge_to_remove = EDGE_SUCC (cond_block, 0);
- if (EDGE_COUNT (edge_to_remove->dest->preds) == 1)
- {
- e->flags |= EDGE_FALLTHRU;
- e->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
- e->probability = profile_probability::always ();
- delete_basic_block (edge_to_remove->dest);
-
- /* Eliminate the COND_EXPR at the end of COND_BLOCK. */
- gsi = gsi_last_bb (cond_block);
- gsi_remove (&gsi, true);
- }
- else
- {
- /* If there are other edges into the middle block make
- CFG cleanup deal with the edge removal to avoid
- updating dominators here in a non-trivial way. */
- gcond *cond = as_a <gcond *> (last_stmt (cond_block));
- if (edge_to_remove->flags & EDGE_TRUE_VALUE)
- gimple_cond_make_false (cond);
- else
- gimple_cond_make_true (cond);
- }
-
- statistics_counter_event (cfun, "Replace PHI with variable", 1);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file,
- "COND_EXPR in block %d and PHI in block %d converted to straightline code.\n",
- cond_block->index,
- bb->index);
-}
-
-/* PR66726: Factor conversion out of COND_EXPR. If the arguments of the PHI
- stmt are CONVERT_STMT, factor out the conversion and perform the conversion
- to the result of PHI stmt. COND_STMT is the controlling predicate.
- Return the newly-created PHI, if any. */
-
-static gphi *
-factor_out_conditional_conversion (edge e0, edge e1, gphi *phi,
- tree arg0, tree arg1, gimple *cond_stmt)
-{
- gimple *arg0_def_stmt = NULL, *arg1_def_stmt = NULL, *new_stmt;
- tree new_arg0 = NULL_TREE, new_arg1 = NULL_TREE;
- tree temp, result;
- gphi *newphi;
- gimple_stmt_iterator gsi, gsi_for_def;
- location_t locus = gimple_location (phi);
- enum tree_code convert_code;
-
- /* Handle only PHI statements with two arguments. TODO: If all
- other arguments to PHI are INTEGER_CST or if their defining
- statement have the same unary operation, we can handle more
- than two arguments too. */
- if (gimple_phi_num_args (phi) != 2)
- return NULL;
-
- /* First canonicalize to simplify tests. */
- if (TREE_CODE (arg0) != SSA_NAME)
- {
- std::swap (arg0, arg1);
- std::swap (e0, e1);
- }
-
- if (TREE_CODE (arg0) != SSA_NAME
- || (TREE_CODE (arg1) != SSA_NAME
- && TREE_CODE (arg1) != INTEGER_CST))
- return NULL;
-
- /* Check if arg0 is an SSA_NAME and the stmt which defines arg0 is
- a conversion. */
- arg0_def_stmt = SSA_NAME_DEF_STMT (arg0);
- if (!gimple_assign_cast_p (arg0_def_stmt))
- return NULL;
-
- /* Use the RHS as new_arg0. */
- convert_code = gimple_assign_rhs_code (arg0_def_stmt);
- new_arg0 = gimple_assign_rhs1 (arg0_def_stmt);
- if (convert_code == VIEW_CONVERT_EXPR)
- {
- new_arg0 = TREE_OPERAND (new_arg0, 0);
- if (!is_gimple_reg_type (TREE_TYPE (new_arg0)))
- return NULL;
- }
- if (TREE_CODE (new_arg0) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_arg0))
- return NULL;
-
- if (TREE_CODE (arg1) == SSA_NAME)
- {
- /* Check if arg1 is an SSA_NAME and the stmt which defines arg1
- is a conversion. */
- arg1_def_stmt = SSA_NAME_DEF_STMT (arg1);
- if (!is_gimple_assign (arg1_def_stmt)
- || gimple_assign_rhs_code (arg1_def_stmt) != convert_code)
- return NULL;
-
- /* Either arg1_def_stmt or arg0_def_stmt should be conditional. */
- if (dominated_by_p (CDI_DOMINATORS, gimple_bb (phi), gimple_bb (arg0_def_stmt))
- && dominated_by_p (CDI_DOMINATORS,
- gimple_bb (phi), gimple_bb (arg1_def_stmt)))
- return NULL;
-
- /* Use the RHS as new_arg1. */
- new_arg1 = gimple_assign_rhs1 (arg1_def_stmt);
- if (convert_code == VIEW_CONVERT_EXPR)
- new_arg1 = TREE_OPERAND (new_arg1, 0);
- if (TREE_CODE (new_arg1) == SSA_NAME
- && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_arg1))
- return NULL;
- }
- else
- {
- /* arg0_def_stmt should be conditional. */
- if (dominated_by_p (CDI_DOMINATORS, gimple_bb (phi), gimple_bb (arg0_def_stmt)))
- return NULL;
- /* If arg1 is an INTEGER_CST, fold it to new type. */
- if (INTEGRAL_TYPE_P (TREE_TYPE (new_arg0))
- && int_fits_type_p (arg1, TREE_TYPE (new_arg0)))
- {
- if (gimple_assign_cast_p (arg0_def_stmt))
- {
- /* For the INTEGER_CST case, we are just moving the
- conversion from one place to another, which can often
- hurt as the conversion moves further away from the
- statement that computes the value. So, perform this
- only if new_arg0 is an operand of COND_STMT, or
- if arg0_def_stmt is the only non-debug stmt in
- its basic block, because then it is possible this
- could enable further optimizations (minmax replacement
- etc.). See PR71016. */
- if (new_arg0 != gimple_cond_lhs (cond_stmt)
- && new_arg0 != gimple_cond_rhs (cond_stmt)
- && gimple_bb (arg0_def_stmt) == e0->src)
- {
- gsi = gsi_for_stmt (arg0_def_stmt);
- gsi_prev_nondebug (&gsi);
- if (!gsi_end_p (gsi))
- {
- if (gassign *assign
- = dyn_cast <gassign *> (gsi_stmt (gsi)))
- {
- tree lhs = gimple_assign_lhs (assign);
- enum tree_code ass_code
- = gimple_assign_rhs_code (assign);
- if (ass_code != MAX_EXPR && ass_code != MIN_EXPR)
- return NULL;
- if (lhs != gimple_assign_rhs1 (arg0_def_stmt))
- return NULL;
- gsi_prev_nondebug (&gsi);
- if (!gsi_end_p (gsi))
- return NULL;
- }
- else
- return NULL;
- }
- gsi = gsi_for_stmt (arg0_def_stmt);
- gsi_next_nondebug (&gsi);
- if (!gsi_end_p (gsi))
- return NULL;
- }
- new_arg1 = fold_convert (TREE_TYPE (new_arg0), arg1);
- }
- else
- return NULL;
- }
- else
- return NULL;
- }
-
- /* If arg0/arg1 have > 1 use, then this transformation actually increases
- the number of expressions evaluated at runtime. */
- if (!has_single_use (arg0)
- || (arg1_def_stmt && !has_single_use (arg1)))
- return NULL;
-
- /* If types of new_arg0 and new_arg1 are different bailout. */
- if (!types_compatible_p (TREE_TYPE (new_arg0), TREE_TYPE (new_arg1)))
- return NULL;
-
- /* Create a new PHI stmt. */
- result = PHI_RESULT (phi);
- temp = make_ssa_name (TREE_TYPE (new_arg0), NULL);
- newphi = create_phi_node (temp, gimple_bb (phi));
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "PHI ");
- print_generic_expr (dump_file, gimple_phi_result (phi));
- fprintf (dump_file,
- " changed to factor conversion out from COND_EXPR.\n");
- fprintf (dump_file, "New stmt with CAST that defines ");
- print_generic_expr (dump_file, result);
- fprintf (dump_file, ".\n");
- }
-
- /* Remove the old cast(s) that has single use. */
- gsi_for_def = gsi_for_stmt (arg0_def_stmt);
- gsi_remove (&gsi_for_def, true);
- release_defs (arg0_def_stmt);
-
- if (arg1_def_stmt)
- {
- gsi_for_def = gsi_for_stmt (arg1_def_stmt);
- gsi_remove (&gsi_for_def, true);
- release_defs (arg1_def_stmt);
- }
-
- add_phi_arg (newphi, new_arg0, e0, locus);
- add_phi_arg (newphi, new_arg1, e1, locus);
-
- /* Create the conversion stmt and insert it. */
- if (convert_code == VIEW_CONVERT_EXPR)
- {
- temp = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (result), temp);
- new_stmt = gimple_build_assign (result, temp);
- }
- else
- new_stmt = gimple_build_assign (result, convert_code, temp);
- gsi = gsi_after_labels (gimple_bb (phi));
- gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
-
- /* Remove the original PHI stmt. */
- gsi = gsi_for_stmt (phi);
- gsi_remove (&gsi, true);
-
- statistics_counter_event (cfun, "factored out cast", 1);
-
- return newphi;
-}
-
-/* Optimize
- # x_5 in range [cst1, cst2] where cst2 = cst1 + 1
- if (x_5 op cstN) # where op is == or != and N is 1 or 2
- goto bb3;
- else
- goto bb4;
- bb3:
- bb4:
- # r_6 = PHI<cst3(2), cst4(3)> # where cst3 == cst4 + 1 or cst4 == cst3 + 1
-
- to r_6 = x_5 + (min (cst3, cst4) - cst1) or
- r_6 = (min (cst3, cst4) + cst1) - x_5 depending on op, N and which
- of cst3 and cst4 is smaller. */
-
-static bool
-two_value_replacement (basic_block cond_bb, basic_block middle_bb,
- edge e1, gphi *phi, tree arg0, tree arg1)
-{
- /* Only look for adjacent integer constants. */
- if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0))
- || !INTEGRAL_TYPE_P (TREE_TYPE (arg1))
- || TREE_CODE (arg0) != INTEGER_CST
- || TREE_CODE (arg1) != INTEGER_CST
- || (tree_int_cst_lt (arg0, arg1)
- ? wi::to_widest (arg0) + 1 != wi::to_widest (arg1)
- : wi::to_widest (arg1) + 1 != wi::to_widest (arg0)))
- return false;
-
- if (!empty_block_p (middle_bb))
- return false;
-
- gimple *stmt = last_stmt (cond_bb);
- tree lhs = gimple_cond_lhs (stmt);
- tree rhs = gimple_cond_rhs (stmt);
-
- if (TREE_CODE (lhs) != SSA_NAME
- || !INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || TREE_CODE (rhs) != INTEGER_CST)
- return false;
-
- switch (gimple_cond_code (stmt))
- {
- case EQ_EXPR:
- case NE_EXPR:
- break;
- default:
- return false;
- }
-
- /* Defer boolean x ? 0 : {1,-1} or x ? {1,-1} : 0 to
- match_simplify_replacement. */
- if (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE
- && (integer_zerop (arg0)
- || integer_zerop (arg1)
- || TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE
- || (TYPE_PRECISION (TREE_TYPE (arg0))
- <= TYPE_PRECISION (TREE_TYPE (lhs)))))
- return false;
-
- wide_int min, max;
- value_range r;
- get_range_query (cfun)->range_of_expr (r, lhs);
-
- if (r.kind () == VR_RANGE)
- {
- min = r.lower_bound ();
- max = r.upper_bound ();
- }
- else
- {
- int prec = TYPE_PRECISION (TREE_TYPE (lhs));
- signop sgn = TYPE_SIGN (TREE_TYPE (lhs));
- min = wi::min_value (prec, sgn);
- max = wi::max_value (prec, sgn);
- }
- if (min + 1 != max
- || (wi::to_wide (rhs) != min
- && wi::to_wide (rhs) != max))
- return false;
-
- /* We need to know which is the true edge and which is the false
- edge so that we know when to invert the condition below. */
- edge true_edge, false_edge;
- extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
- if ((gimple_cond_code (stmt) == EQ_EXPR)
- ^ (wi::to_wide (rhs) == max)
- ^ (e1 == false_edge))
- std::swap (arg0, arg1);
-
- tree type;
- if (TYPE_PRECISION (TREE_TYPE (lhs)) == TYPE_PRECISION (TREE_TYPE (arg0)))
- {
- /* Avoid performing the arithmetics in bool type which has different
- semantics, otherwise prefer unsigned types from the two with
- the same precision. */
- if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE
- || !TYPE_UNSIGNED (TREE_TYPE (arg0)))
- type = TREE_TYPE (lhs);
- else
- type = TREE_TYPE (arg0);
- }
- else if (TYPE_PRECISION (TREE_TYPE (lhs)) > TYPE_PRECISION (TREE_TYPE (arg0)))
- type = TREE_TYPE (lhs);
- else
- type = TREE_TYPE (arg0);
-
- min = wide_int::from (min, TYPE_PRECISION (type),
- TYPE_SIGN (TREE_TYPE (lhs)));
- wide_int a = wide_int::from (wi::to_wide (arg0), TYPE_PRECISION (type),
- TYPE_SIGN (TREE_TYPE (arg0)));
- enum tree_code code;
- wi::overflow_type ovf;
- if (tree_int_cst_lt (arg0, arg1))
- {
- code = PLUS_EXPR;
- a -= min;
- if (!TYPE_UNSIGNED (type))
- {
- /* lhs is known to be in range [min, min+1] and we want to add a
- to it. Check if that operation can overflow for those 2 values
- and if yes, force unsigned type. */
- wi::add (min + (wi::neg_p (a) ? 0 : 1), a, SIGNED, &ovf);
- if (ovf)
- type = unsigned_type_for (type);
- }
- }
- else
- {
- code = MINUS_EXPR;
- a += min;
- if (!TYPE_UNSIGNED (type))
- {
- /* lhs is known to be in range [min, min+1] and we want to subtract
- it from a. Check if that operation can overflow for those 2
- values and if yes, force unsigned type. */
- wi::sub (a, min + (wi::neg_p (min) ? 0 : 1), SIGNED, &ovf);
- if (ovf)
- type = unsigned_type_for (type);
- }
- }
-
- tree arg = wide_int_to_tree (type, a);
- gimple_seq stmts = NULL;
- lhs = gimple_convert (&stmts, type, lhs);
- tree new_rhs;
- if (code == PLUS_EXPR)
- new_rhs = gimple_build (&stmts, PLUS_EXPR, type, lhs, arg);
- else
- new_rhs = gimple_build (&stmts, MINUS_EXPR, type, arg, lhs);
- new_rhs = gimple_convert (&stmts, TREE_TYPE (arg0), new_rhs);
- gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
- gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT);
-
- replace_phi_edge_with_variable (cond_bb, e1, phi, new_rhs);
-
- /* Note that we optimized this PHI. */
- return true;
-}
-
-/* Return TRUE if SEQ/OP pair should be allowed during early phiopt.
- Currently this is to allow MIN/MAX and ABS/NEGATE and constants. */
-static bool
-phiopt_early_allow (gimple_seq &seq, gimple_match_op &op)
-{
- /* Don't allow functions. */
- if (!op.code.is_tree_code ())
- return false;
- tree_code code = (tree_code)op.code;
-
- /* For non-empty sequence, only allow one statement. */
- if (!gimple_seq_empty_p (seq))
- {
- /* Check to make sure op was already a SSA_NAME. */
- if (code != SSA_NAME)
- return false;
- if (!gimple_seq_singleton_p (seq))
- return false;
- gimple *stmt = gimple_seq_first_stmt (seq);
- /* Only allow assignments. */
- if (!is_gimple_assign (stmt))
- return false;
- if (gimple_assign_lhs (stmt) != op.ops[0])
- return false;
- code = gimple_assign_rhs_code (stmt);
- }
-
- switch (code)
- {
- case MIN_EXPR:
- case MAX_EXPR:
- case ABS_EXPR:
- case ABSU_EXPR:
- case NEGATE_EXPR:
- case SSA_NAME:
- return true;
- case INTEGER_CST:
- case REAL_CST:
- case VECTOR_CST:
- case FIXED_CST:
- return true;
- default:
- return false;
- }
-}
-
-/* gimple_simplify_phiopt is like gimple_simplify but designed for PHIOPT.
- Return NULL if nothing can be simplified or the resulting simplified value
- with parts pushed if EARLY_P was true. Also rejects non allowed tree code
- if EARLY_P is set.
- Takes the comparison from COMP_STMT and two args, ARG0 and ARG1 and tries
- to simplify CMP ? ARG0 : ARG1.
- Also try to simplify (!CMP) ? ARG1 : ARG0 if the non-inverse failed. */
-static tree
-gimple_simplify_phiopt (bool early_p, tree type, gimple *comp_stmt,
- tree arg0, tree arg1,
- gimple_seq *seq)
-{
- tree result;
- gimple_seq seq1 = NULL;
- enum tree_code comp_code = gimple_cond_code (comp_stmt);
- location_t loc = gimple_location (comp_stmt);
- tree cmp0 = gimple_cond_lhs (comp_stmt);
- tree cmp1 = gimple_cond_rhs (comp_stmt);
- /* To handle special cases like floating point comparison, it is easier and
- less error-prone to build a tree and gimplify it on the fly though it is
- less efficient.
- Don't use fold_build2 here as that might create (bool)a instead of just
- "a != 0". */
- tree cond = build2_loc (loc, comp_code, boolean_type_node,
- cmp0, cmp1);
- gimple_match_op op (gimple_match_cond::UNCOND,
- COND_EXPR, type, cond, arg0, arg1);
-
- if (op.resimplify (&seq1, follow_all_ssa_edges))
- {
- /* Early we want only to allow some generated tree codes. */
- if (!early_p
- || phiopt_early_allow (seq1, op))
- {
- result = maybe_push_res_to_seq (&op, &seq1);
- if (result)
- {
- if (loc != UNKNOWN_LOCATION)
- annotate_all_with_location (seq1, loc);
- gimple_seq_add_seq_without_update (seq, seq1);
- return result;
- }
- }
- }
- gimple_seq_discard (seq1);
- seq1 = NULL;
-
- /* Try the inverted comparison, that is !COMP ? ARG1 : ARG0. */
- comp_code = invert_tree_comparison (comp_code, HONOR_NANS (cmp0));
-
- if (comp_code == ERROR_MARK)
- return NULL;
-
- cond = build2_loc (loc,
- comp_code, boolean_type_node,
- cmp0, cmp1);
- gimple_match_op op1 (gimple_match_cond::UNCOND,
- COND_EXPR, type, cond, arg1, arg0);
-
- if (op1.resimplify (&seq1, follow_all_ssa_edges))
- {
- /* Early we want only to allow some generated tree codes. */
- if (!early_p
- || phiopt_early_allow (seq1, op1))
- {
- result = maybe_push_res_to_seq (&op1, &seq1);
- if (result)
- {
- if (loc != UNKNOWN_LOCATION)
- annotate_all_with_location (seq1, loc);
- gimple_seq_add_seq_without_update (seq, seq1);
- return result;
- }
- }
- }
- gimple_seq_discard (seq1);
-
- return NULL;
-}
-
-/* The function match_simplify_replacement does the main work of doing the
- replacement using match and simplify. Return true if the replacement is done.
- Otherwise return false.
- BB is the basic block where the replacement is going to be done on. ARG0
- is argument 0 from PHI. Likewise for ARG1. */
-
-static bool
-match_simplify_replacement (basic_block cond_bb, basic_block middle_bb,
- edge e0, edge e1, gphi *phi,
- tree arg0, tree arg1, bool early_p)
-{
- gimple *stmt;
- gimple_stmt_iterator gsi;
- edge true_edge, false_edge;
- gimple_seq seq = NULL;
- tree result;
- gimple *stmt_to_move = NULL;
-
- /* Special case A ? B : B as this will always simplify to B. */
- if (operand_equal_for_phi_arg_p (arg0, arg1))
- return false;
-
- /* If the basic block only has a cheap preparation statement,
- allow it and move it once the transformation is done. */
- if (!empty_block_p (middle_bb))
- {
- if (!single_pred_p (middle_bb))
- return false;
-
- stmt_to_move = last_and_only_stmt (middle_bb);
- if (!stmt_to_move)
- return false;
-
- if (gimple_vuse (stmt_to_move))
- return false;
-
- if (gimple_could_trap_p (stmt_to_move)
- || gimple_has_side_effects (stmt_to_move))
- return false;
-
- if (gimple_uses_undefined_value_p (stmt_to_move))
- return false;
-
- /* Allow assignments and not no calls.
- As const calls don't match any of the above, yet they could
- still have some side-effects - they could contain
- gimple_could_trap_p statements, like floating point
- exceptions or integer division by zero. See PR70586.
- FIXME: perhaps gimple_has_side_effects or gimple_could_trap_p
- should handle this. */
- if (!is_gimple_assign (stmt_to_move))
- return false;
-
- tree lhs = gimple_assign_lhs (stmt_to_move);
- gimple *use_stmt;
- use_operand_p use_p;
-
- /* Allow only a statement which feeds into the phi. */
- if (!lhs || TREE_CODE (lhs) != SSA_NAME
- || !single_imm_use (lhs, &use_p, &use_stmt)
- || use_stmt != phi)
- return false;
- }
-
- /* At this point we know we have a GIMPLE_COND with two successors.
- One successor is BB, the other successor is an empty block which
- falls through into BB.
-
- There is a single PHI node at the join point (BB).
-
- So, given the condition COND, and the two PHI arguments, match and simplify
- can happen on (COND) ? arg0 : arg1. */
-
- stmt = last_stmt (cond_bb);
-
- /* We need to know which is the true edge and which is the false
- edge so that we know when to invert the condition below. */
- extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
- if (e1 == true_edge || e0 == false_edge)
- std::swap (arg0, arg1);
-
- tree type = TREE_TYPE (gimple_phi_result (phi));
- result = gimple_simplify_phiopt (early_p, type, stmt,
- arg0, arg1,
- &seq);
- if (!result)
- return false;
-
- gsi = gsi_last_bb (cond_bb);
- /* Insert the sequence generated from gimple_simplify_phiopt. */
- if (seq)
- gsi_insert_seq_before (&gsi, seq, GSI_CONTINUE_LINKING);
-
- /* If there was a statement to move and the result of the statement
- is going to be used, move it to right before the original
- conditional. */
- if (stmt_to_move
- && (gimple_assign_lhs (stmt_to_move) == result
- || !has_single_use (gimple_assign_lhs (stmt_to_move))))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "statement un-sinked:\n");
- print_gimple_stmt (dump_file, stmt_to_move, 0,
- TDF_VOPS|TDF_MEMSYMS);
- }
- gimple_stmt_iterator gsi1 = gsi_for_stmt (stmt_to_move);
- gsi_move_before (&gsi1, &gsi);
- reset_flow_sensitive_info (gimple_assign_lhs (stmt_to_move));
- }
-
- replace_phi_edge_with_variable (cond_bb, e1, phi, result);
-
- /* Add Statistic here even though replace_phi_edge_with_variable already
- does it as we want to be able to count when match-simplify happens vs
- the others. */
- statistics_counter_event (cfun, "match-simplify PHI replacement", 1);
-
- /* Note that we optimized this PHI. */
- return true;
-}
-
-/* Update *ARG which is defined in STMT so that it contains the
- computed value if that seems profitable. Return true if the
- statement is made dead by that rewriting. */
-
-static bool
-jump_function_from_stmt (tree *arg, gimple *stmt)
-{
- enum tree_code code = gimple_assign_rhs_code (stmt);
- if (code == ADDR_EXPR)
- {
- /* For arg = &p->i transform it to p, if possible. */
- tree rhs1 = gimple_assign_rhs1 (stmt);
- poly_int64 offset;
- tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (rhs1, 0),
- &offset);
- if (tem
- && TREE_CODE (tem) == MEM_REF
- && known_eq (mem_ref_offset (tem) + offset, 0))
- {
- *arg = TREE_OPERAND (tem, 0);
- return true;
- }
- }
- /* TODO: Much like IPA-CP jump-functions we want to handle constant
- additions symbolically here, and we'd need to update the comparison
- code that compares the arg + cst tuples in our caller. For now the
- code above exactly handles the VEC_BASE pattern from vec.h. */
- return false;
-}
-
-/* RHS is a source argument in a BIT_AND_EXPR which feeds a conditional
- of the form SSA_NAME NE 0.
-
- If RHS is fed by a simple EQ_EXPR comparison of two values, see if
- the two input values of the EQ_EXPR match arg0 and arg1.
-
- If so update *code and return TRUE. Otherwise return FALSE. */
-
-static bool
-rhs_is_fed_for_value_replacement (const_tree arg0, const_tree arg1,
- enum tree_code *code, const_tree rhs)
-{
- /* Obviously if RHS is not an SSA_NAME, we can't look at the defining
- statement. */
- if (TREE_CODE (rhs) == SSA_NAME)
- {
- gimple *def1 = SSA_NAME_DEF_STMT (rhs);
-
- /* Verify the defining statement has an EQ_EXPR on the RHS. */
- if (is_gimple_assign (def1) && gimple_assign_rhs_code (def1) == EQ_EXPR)
- {
- /* Finally verify the source operands of the EQ_EXPR are equal
- to arg0 and arg1. */
- tree op0 = gimple_assign_rhs1 (def1);
- tree op1 = gimple_assign_rhs2 (def1);
- if ((operand_equal_for_phi_arg_p (arg0, op0)
- && operand_equal_for_phi_arg_p (arg1, op1))
- || (operand_equal_for_phi_arg_p (arg0, op1)
- && operand_equal_for_phi_arg_p (arg1, op0)))
- {
- /* We will perform the optimization. */
- *code = gimple_assign_rhs_code (def1);
- return true;
- }
- }
- }
- return false;
-}
-
-/* Return TRUE if arg0/arg1 are equal to the rhs/lhs or lhs/rhs of COND.
-
- Also return TRUE if arg0/arg1 are equal to the source arguments of a
- an EQ comparison feeding a BIT_AND_EXPR which feeds COND.
-
- Return FALSE otherwise. */
-
-static bool
-operand_equal_for_value_replacement (const_tree arg0, const_tree arg1,
- enum tree_code *code, gimple *cond)
-{
- gimple *def;
- tree lhs = gimple_cond_lhs (cond);
- tree rhs = gimple_cond_rhs (cond);
-
- if ((operand_equal_for_phi_arg_p (arg0, lhs)
- && operand_equal_for_phi_arg_p (arg1, rhs))
- || (operand_equal_for_phi_arg_p (arg1, lhs)
- && operand_equal_for_phi_arg_p (arg0, rhs)))
- return true;
-
- /* Now handle more complex case where we have an EQ comparison
- which feeds a BIT_AND_EXPR which feeds COND.
-
- First verify that COND is of the form SSA_NAME NE 0. */
- if (*code != NE_EXPR || !integer_zerop (rhs)
- || TREE_CODE (lhs) != SSA_NAME)
- return false;
-
- /* Now ensure that SSA_NAME is set by a BIT_AND_EXPR. */
- def = SSA_NAME_DEF_STMT (lhs);
- if (!is_gimple_assign (def) || gimple_assign_rhs_code (def) != BIT_AND_EXPR)
- return false;
-
- /* Now verify arg0/arg1 correspond to the source arguments of an
- EQ comparison feeding the BIT_AND_EXPR. */
-
- tree tmp = gimple_assign_rhs1 (def);
- if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp))
- return true;
-
- tmp = gimple_assign_rhs2 (def);
- if (rhs_is_fed_for_value_replacement (arg0, arg1, code, tmp))
- return true;
-
- return false;
-}
-
-/* Returns true if ARG is a neutral element for operation CODE
- on the RIGHT side. */
-
-static bool
-neutral_element_p (tree_code code, tree arg, bool right)
-{
- switch (code)
- {
- case PLUS_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- return integer_zerop (arg);
-
- case LROTATE_EXPR:
- case RROTATE_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case MINUS_EXPR:
- case POINTER_PLUS_EXPR:
- return right && integer_zerop (arg);
-
- case MULT_EXPR:
- return integer_onep (arg);
-
- case TRUNC_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case EXACT_DIV_EXPR:
- return right && integer_onep (arg);
-
- case BIT_AND_EXPR:
- return integer_all_onesp (arg);
-
- default:
- return false;
- }
-}
-
-/* Returns true if ARG is an absorbing element for operation CODE. */
-
-static bool
-absorbing_element_p (tree_code code, tree arg, bool right, tree rval)
-{
- switch (code)
- {
- case BIT_IOR_EXPR:
- return integer_all_onesp (arg);
-
- case MULT_EXPR:
- case BIT_AND_EXPR:
- return integer_zerop (arg);
-
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case LROTATE_EXPR:
- case RROTATE_EXPR:
- return !right && integer_zerop (arg);
-
- case TRUNC_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case EXACT_DIV_EXPR:
- case TRUNC_MOD_EXPR:
- case CEIL_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case ROUND_MOD_EXPR:
- return (!right
- && integer_zerop (arg)
- && tree_single_nonzero_warnv_p (rval, NULL));
-
- default:
- return false;
- }
-}
-
-/* The function value_replacement does the main work of doing the value
- replacement. Return non-zero if the replacement is done. Otherwise return
- 0. If we remove the middle basic block, return 2.
- BB is the basic block where the replacement is going to be done on. ARG0
- is argument 0 from the PHI. Likewise for ARG1. */
-
-static int
-value_replacement (basic_block cond_bb, basic_block middle_bb,
- edge e0, edge e1, gphi *phi, tree arg0, tree arg1)
-{
- gimple_stmt_iterator gsi;
- gimple *cond;
- edge true_edge, false_edge;
- enum tree_code code;
- bool empty_or_with_defined_p = true;
-
- /* If the type says honor signed zeros we cannot do this
- optimization. */
- if (HONOR_SIGNED_ZEROS (arg1))
- return 0;
-
- /* If there is a statement in MIDDLE_BB that defines one of the PHI
- arguments, then adjust arg0 or arg1. */
- gsi = gsi_start_nondebug_after_labels_bb (middle_bb);
- while (!gsi_end_p (gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- tree lhs;
- gsi_next_nondebug (&gsi);
- if (!is_gimple_assign (stmt))
- {
- if (gimple_code (stmt) != GIMPLE_PREDICT
- && gimple_code (stmt) != GIMPLE_NOP)
- empty_or_with_defined_p = false;
- continue;
- }
- /* Now try to adjust arg0 or arg1 according to the computation
- in the statement. */
- lhs = gimple_assign_lhs (stmt);
- if (!(lhs == arg0
- && jump_function_from_stmt (&arg0, stmt))
- || (lhs == arg1
- && jump_function_from_stmt (&arg1, stmt)))
- empty_or_with_defined_p = false;
- }
-
- cond = last_stmt (cond_bb);
- code = gimple_cond_code (cond);
-
- /* This transformation is only valid for equality comparisons. */
- if (code != NE_EXPR && code != EQ_EXPR)
- return 0;
-
- /* We need to know which is the true edge and which is the false
- edge so that we know if have abs or negative abs. */
- extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
-
- /* At this point we know we have a COND_EXPR with two successors.
- One successor is BB, the other successor is an empty block which
- falls through into BB.
-
- The condition for the COND_EXPR is known to be NE_EXPR or EQ_EXPR.
-
- There is a single PHI node at the join point (BB) with two arguments.
-
- We now need to verify that the two arguments in the PHI node match
- the two arguments to the equality comparison. */
-
- if (operand_equal_for_value_replacement (arg0, arg1, &code, cond))
- {
- edge e;
- tree arg;
-
- /* For NE_EXPR, we want to build an assignment result = arg where
- arg is the PHI argument associated with the true edge. For
- EQ_EXPR we want the PHI argument associated with the false edge. */
- e = (code == NE_EXPR ? true_edge : false_edge);
-
- /* Unfortunately, E may not reach BB (it may instead have gone to
- OTHER_BLOCK). If that is the case, then we want the single outgoing
- edge from OTHER_BLOCK which reaches BB and represents the desired
- path from COND_BLOCK. */
- if (e->dest == middle_bb)
- e = single_succ_edge (e->dest);
-
- /* Now we know the incoming edge to BB that has the argument for the
- RHS of our new assignment statement. */
- if (e0 == e)
- arg = arg0;
- else
- arg = arg1;
-
- /* If the middle basic block was empty or is defining the
- PHI arguments and this is a single phi where the args are different
- for the edges e0 and e1 then we can remove the middle basic block. */
- if (empty_or_with_defined_p
- && single_non_singleton_phi_for_edges (phi_nodes (gimple_bb (phi)),
- e0, e1) == phi)
- {
- replace_phi_edge_with_variable (cond_bb, e1, phi, arg);
- /* Note that we optimized this PHI. */
- return 2;
- }
- else
- {
- if (!single_pred_p (middle_bb))
- return 0;
- statistics_counter_event (cfun, "Replace PHI with "
- "variable/value_replacement", 1);
-
- /* Replace the PHI arguments with arg. */
- SET_PHI_ARG_DEF (phi, e0->dest_idx, arg);
- SET_PHI_ARG_DEF (phi, e1->dest_idx, arg);
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "PHI ");
- print_generic_expr (dump_file, gimple_phi_result (phi));
- fprintf (dump_file, " reduced for COND_EXPR in block %d to ",
- cond_bb->index);
- print_generic_expr (dump_file, arg);
- fprintf (dump_file, ".\n");
- }
- return 1;
- }
- }
-
- if (!single_pred_p (middle_bb))
- return 0;
-
- /* Now optimize (x != 0) ? x + y : y to just x + y. */
- gsi = gsi_last_nondebug_bb (middle_bb);
- if (gsi_end_p (gsi))
- return 0;
-
- gimple *assign = gsi_stmt (gsi);
- if (!is_gimple_assign (assign)
- || gimple_assign_rhs_class (assign) != GIMPLE_BINARY_RHS
- || (!INTEGRAL_TYPE_P (TREE_TYPE (arg0))
- && !POINTER_TYPE_P (TREE_TYPE (arg0))))
- return 0;
-
- /* Punt if there are (degenerate) PHIs in middle_bb, there should not be. */
- if (!gimple_seq_empty_p (phi_nodes (middle_bb)))
- return 0;
-
- /* Allow up to 2 cheap preparation statements that prepare argument
- for assign, e.g.:
- if (y_4 != 0)
- goto <bb 3>;
- else
- goto <bb 4>;
- <bb 3>:
- _1 = (int) y_4;
- iftmp.0_6 = x_5(D) r<< _1;
- <bb 4>:
- # iftmp.0_2 = PHI <iftmp.0_6(3), x_5(D)(2)>
- or:
- if (y_3(D) == 0)
- goto <bb 4>;
- else
- goto <bb 3>;
- <bb 3>:
- y_4 = y_3(D) & 31;
- _1 = (int) y_4;
- _6 = x_5(D) r<< _1;
- <bb 4>:
- # _2 = PHI <x_5(D)(2), _6(3)> */
- gimple *prep_stmt[2] = { NULL, NULL };
- int prep_cnt;
- for (prep_cnt = 0; ; prep_cnt++)
- {
- gsi_prev_nondebug (&gsi);
- if (gsi_end_p (gsi))
- break;
-
- gimple *g = gsi_stmt (gsi);
- if (gimple_code (g) == GIMPLE_LABEL)
- break;
-
- if (prep_cnt == 2 || !is_gimple_assign (g))
- return 0;
-
- tree lhs = gimple_assign_lhs (g);
- tree rhs1 = gimple_assign_rhs1 (g);
- use_operand_p use_p;
- gimple *use_stmt;
- if (TREE_CODE (lhs) != SSA_NAME
- || TREE_CODE (rhs1) != SSA_NAME
- || !INTEGRAL_TYPE_P (TREE_TYPE (lhs))
- || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1))
- || !single_imm_use (lhs, &use_p, &use_stmt)
- || use_stmt != (prep_cnt ? prep_stmt[prep_cnt - 1] : assign))
- return 0;
- switch (gimple_assign_rhs_code (g))
- {
- CASE_CONVERT:
- break;
- case PLUS_EXPR:
- case BIT_AND_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- if (TREE_CODE (gimple_assign_rhs2 (g)) != INTEGER_CST)
- return 0;
- break;
- default:
- return 0;
- }
- prep_stmt[prep_cnt] = g;
- }
-
- /* Only transform if it removes the condition. */
- if (!single_non_singleton_phi_for_edges (phi_nodes (gimple_bb (phi)), e0, e1))
- return 0;
-
- /* Size-wise, this is always profitable. */
- if (optimize_bb_for_speed_p (cond_bb)
- /* The special case is useless if it has a low probability. */
- && profile_status_for_fn (cfun) != PROFILE_ABSENT
- && EDGE_PRED (middle_bb, 0)->probability < profile_probability::even ()
- /* If assign is cheap, there is no point avoiding it. */
- && estimate_num_insns_seq (bb_seq (middle_bb), &eni_time_weights)
- >= 3 * estimate_num_insns (cond, &eni_time_weights))
- return 0;
-
- tree lhs = gimple_assign_lhs (assign);
- tree rhs1 = gimple_assign_rhs1 (assign);
- tree rhs2 = gimple_assign_rhs2 (assign);
- enum tree_code code_def = gimple_assign_rhs_code (assign);
- tree cond_lhs = gimple_cond_lhs (cond);
- tree cond_rhs = gimple_cond_rhs (cond);
-
- /* Propagate the cond_rhs constant through preparation stmts,
- make sure UB isn't invoked while doing that. */
- for (int i = prep_cnt - 1; i >= 0; --i)
- {
- gimple *g = prep_stmt[i];
- tree grhs1 = gimple_assign_rhs1 (g);
- if (!operand_equal_for_phi_arg_p (cond_lhs, grhs1))
- return 0;
- cond_lhs = gimple_assign_lhs (g);
- cond_rhs = fold_convert (TREE_TYPE (grhs1), cond_rhs);
- if (TREE_CODE (cond_rhs) != INTEGER_CST
- || TREE_OVERFLOW (cond_rhs))
- return 0;
- if (gimple_assign_rhs_class (g) == GIMPLE_BINARY_RHS)
- {
- cond_rhs = int_const_binop (gimple_assign_rhs_code (g), cond_rhs,
- gimple_assign_rhs2 (g));
- if (TREE_OVERFLOW (cond_rhs))
- return 0;
- }
- cond_rhs = fold_convert (TREE_TYPE (cond_lhs), cond_rhs);
- if (TREE_CODE (cond_rhs) != INTEGER_CST
- || TREE_OVERFLOW (cond_rhs))
- return 0;
- }
-
- if (((code == NE_EXPR && e1 == false_edge)
- || (code == EQ_EXPR && e1 == true_edge))
- && arg0 == lhs
- && ((arg1 == rhs1
- && operand_equal_for_phi_arg_p (rhs2, cond_lhs)
- && neutral_element_p (code_def, cond_rhs, true))
- || (arg1 == rhs2
- && operand_equal_for_phi_arg_p (rhs1, cond_lhs)
- && neutral_element_p (code_def, cond_rhs, false))
- || (operand_equal_for_phi_arg_p (arg1, cond_rhs)
- && ((operand_equal_for_phi_arg_p (rhs2, cond_lhs)
- && absorbing_element_p (code_def, cond_rhs, true, rhs2))
- || (operand_equal_for_phi_arg_p (rhs1, cond_lhs)
- && absorbing_element_p (code_def,
- cond_rhs, false, rhs2))))))
- {
- gsi = gsi_for_stmt (cond);
- /* Moving ASSIGN might change VR of lhs, e.g. when moving u_6
- def-stmt in:
- if (n_5 != 0)
- goto <bb 3>;
- else
- goto <bb 4>;
-
- <bb 3>:
- # RANGE [0, 4294967294]
- u_6 = n_5 + 4294967295;
-
- <bb 4>:
- # u_3 = PHI <u_6(3), 4294967295(2)> */
- reset_flow_sensitive_info (lhs);
- gimple_stmt_iterator gsi_from;
- for (int i = prep_cnt - 1; i >= 0; --i)
- {
- tree plhs = gimple_assign_lhs (prep_stmt[i]);
- reset_flow_sensitive_info (plhs);
- gsi_from = gsi_for_stmt (prep_stmt[i]);
- gsi_move_before (&gsi_from, &gsi);
- }
- gsi_from = gsi_for_stmt (assign);
- gsi_move_before (&gsi_from, &gsi);
- replace_phi_edge_with_variable (cond_bb, e1, phi, lhs);
- return 2;
- }
-
- return 0;
-}
-
-/* The function minmax_replacement does the main work of doing the minmax
- replacement. Return true if the replacement is done. Otherwise return
- false.
- BB is the basic block where the replacement is going to be done on. ARG0
- is argument 0 from the PHI. Likewise for ARG1. */
-
-static bool
-minmax_replacement (basic_block cond_bb, basic_block middle_bb,
- edge e0, edge e1, gphi *phi, tree arg0, tree arg1)
-{
- tree result;
- edge true_edge, false_edge;
- enum tree_code minmax, ass_code;
- tree smaller, larger, arg_true, arg_false;
- gimple_stmt_iterator gsi, gsi_from;
-
- tree type = TREE_TYPE (PHI_RESULT (phi));
-
- /* The optimization may be unsafe due to NaNs. */
- if (HONOR_NANS (type) || HONOR_SIGNED_ZEROS (type))
- return false;
-
- gcond *cond = as_a <gcond *> (last_stmt (cond_bb));
- enum tree_code cmp = gimple_cond_code (cond);
- tree rhs = gimple_cond_rhs (cond);
-
- /* Turn EQ/NE of extreme values to order comparisons. */
- if ((cmp == NE_EXPR || cmp == EQ_EXPR)
- && TREE_CODE (rhs) == INTEGER_CST
- && INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
- {
- if (wi::eq_p (wi::to_wide (rhs), wi::min_value (TREE_TYPE (rhs))))
- {
- cmp = (cmp == EQ_EXPR) ? LT_EXPR : GE_EXPR;
- rhs = wide_int_to_tree (TREE_TYPE (rhs),
- wi::min_value (TREE_TYPE (rhs)) + 1);
- }
- else if (wi::eq_p (wi::to_wide (rhs), wi::max_value (TREE_TYPE (rhs))))
- {
- cmp = (cmp == EQ_EXPR) ? GT_EXPR : LE_EXPR;
- rhs = wide_int_to_tree (TREE_TYPE (rhs),
- wi::max_value (TREE_TYPE (rhs)) - 1);
- }
- }
-
- /* This transformation is only valid for order comparisons. Record which
- operand is smaller/larger if the result of the comparison is true. */
- tree alt_smaller = NULL_TREE;
- tree alt_larger = NULL_TREE;
- if (cmp == LT_EXPR || cmp == LE_EXPR)
- {
- smaller = gimple_cond_lhs (cond);
- larger = rhs;
- /* If we have smaller < CST it is equivalent to smaller <= CST-1.
- Likewise smaller <= CST is equivalent to smaller < CST+1. */
- if (TREE_CODE (larger) == INTEGER_CST
- && INTEGRAL_TYPE_P (TREE_TYPE (larger)))
- {
- if (cmp == LT_EXPR)
- {
- wi::overflow_type overflow;
- wide_int alt = wi::sub (wi::to_wide (larger), 1,
- TYPE_SIGN (TREE_TYPE (larger)),
- &overflow);
- if (! overflow)
- alt_larger = wide_int_to_tree (TREE_TYPE (larger), alt);
- }
- else
- {
- wi::overflow_type overflow;
- wide_int alt = wi::add (wi::to_wide (larger), 1,
- TYPE_SIGN (TREE_TYPE (larger)),
- &overflow);
- if (! overflow)
- alt_larger = wide_int_to_tree (TREE_TYPE (larger), alt);
- }
- }
- }
- else if (cmp == GT_EXPR || cmp == GE_EXPR)
- {
- smaller = rhs;
- larger = gimple_cond_lhs (cond);
- /* If we have larger > CST it is equivalent to larger >= CST+1.
- Likewise larger >= CST is equivalent to larger > CST-1. */
- if (TREE_CODE (smaller) == INTEGER_CST
- && INTEGRAL_TYPE_P (TREE_TYPE (smaller)))
- {
- wi::overflow_type overflow;
- if (cmp == GT_EXPR)
- {
- wide_int alt = wi::add (wi::to_wide (smaller), 1,
- TYPE_SIGN (TREE_TYPE (smaller)),
- &overflow);
- if (! overflow)
- alt_smaller = wide_int_to_tree (TREE_TYPE (smaller), alt);
- }
- else
- {
- wide_int alt = wi::sub (wi::to_wide (smaller), 1,
- TYPE_SIGN (TREE_TYPE (smaller)),
- &overflow);
- if (! overflow)
- alt_smaller = wide_int_to_tree (TREE_TYPE (smaller), alt);
- }
- }
- }
- else
- return false;
-
- /* Handle the special case of (signed_type)x < 0 being equivalent
- to x > MAX_VAL(signed_type) and (signed_type)x >= 0 equivalent
- to x <= MAX_VAL(signed_type). */
- if ((cmp == GE_EXPR || cmp == LT_EXPR)
- && INTEGRAL_TYPE_P (type)
- && TYPE_UNSIGNED (type)
- && integer_zerop (rhs))
- {
- tree op = gimple_cond_lhs (cond);
- if (TREE_CODE (op) == SSA_NAME
- && INTEGRAL_TYPE_P (TREE_TYPE (op))
- && !TYPE_UNSIGNED (TREE_TYPE (op)))
- {
- gimple *def_stmt = SSA_NAME_DEF_STMT (op);
- if (gimple_assign_cast_p (def_stmt))
- {
- tree op1 = gimple_assign_rhs1 (def_stmt);
- if (INTEGRAL_TYPE_P (TREE_TYPE (op1))
- && TYPE_UNSIGNED (TREE_TYPE (op1))
- && (TYPE_PRECISION (TREE_TYPE (op))
- == TYPE_PRECISION (TREE_TYPE (op1)))
- && useless_type_conversion_p (type, TREE_TYPE (op1)))
- {
- wide_int w1 = wi::max_value (TREE_TYPE (op));
- wide_int w2 = wi::add (w1, 1);
- if (cmp == LT_EXPR)
- {
- larger = op1;
- smaller = wide_int_to_tree (TREE_TYPE (op1), w1);
- alt_smaller = wide_int_to_tree (TREE_TYPE (op1), w2);
- alt_larger = NULL_TREE;
- }
- else
- {
- smaller = op1;
- larger = wide_int_to_tree (TREE_TYPE (op1), w1);
- alt_larger = wide_int_to_tree (TREE_TYPE (op1), w2);
- alt_smaller = NULL_TREE;
- }
- }
- }
- }
- }
-
- /* We need to know which is the true edge and which is the false
- edge so that we know if have abs or negative abs. */
- extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
-
- /* Forward the edges over the middle basic block. */
- if (true_edge->dest == middle_bb)
- true_edge = EDGE_SUCC (true_edge->dest, 0);
- if (false_edge->dest == middle_bb)
- false_edge = EDGE_SUCC (false_edge->dest, 0);
-
- if (true_edge == e0)
- {
- gcc_assert (false_edge == e1);
- arg_true = arg0;
- arg_false = arg1;
- }
- else
- {
- gcc_assert (false_edge == e0);
- gcc_assert (true_edge == e1);
- arg_true = arg1;
- arg_false = arg0;
- }
-
- if (empty_block_p (middle_bb))
- {
- if ((operand_equal_for_phi_arg_p (arg_true, smaller)
- || (alt_smaller
- && operand_equal_for_phi_arg_p (arg_true, alt_smaller)))
- && (operand_equal_for_phi_arg_p (arg_false, larger)
- || (alt_larger
- && operand_equal_for_phi_arg_p (arg_true, alt_larger))))
- {
- /* Case
-
- if (smaller < larger)
- rslt = smaller;
- else
- rslt = larger; */
- minmax = MIN_EXPR;
- }
- else if ((operand_equal_for_phi_arg_p (arg_false, smaller)
- || (alt_smaller
- && operand_equal_for_phi_arg_p (arg_false, alt_smaller)))
- && (operand_equal_for_phi_arg_p (arg_true, larger)
- || (alt_larger
- && operand_equal_for_phi_arg_p (arg_true, alt_larger))))
- minmax = MAX_EXPR;
- else
- return false;
- }
- else
- {
- /* Recognize the following case, assuming d <= u:
-
- if (a <= u)
- b = MAX (a, d);
- x = PHI <b, u>
-
- This is equivalent to
-
- b = MAX (a, d);
- x = MIN (b, u); */
-
- gimple *assign = last_and_only_stmt (middle_bb);
- tree lhs, op0, op1, bound;
-
- if (!single_pred_p (middle_bb))
- return false;
-
- if (!assign
- || gimple_code (assign) != GIMPLE_ASSIGN)
- return false;
-
- lhs = gimple_assign_lhs (assign);
- ass_code = gimple_assign_rhs_code (assign);
- if (ass_code != MAX_EXPR && ass_code != MIN_EXPR)
- return false;
- op0 = gimple_assign_rhs1 (assign);
- op1 = gimple_assign_rhs2 (assign);
-
- if (true_edge->src == middle_bb)
- {
- /* We got here if the condition is true, i.e., SMALLER < LARGER. */
- if (!operand_equal_for_phi_arg_p (lhs, arg_true))
- return false;
-
- if (operand_equal_for_phi_arg_p (arg_false, larger)
- || (alt_larger
- && operand_equal_for_phi_arg_p (arg_false, alt_larger)))
- {
- /* Case
-
- if (smaller < larger)
- {
- r' = MAX_EXPR (smaller, bound)
- }
- r = PHI <r', larger> --> to be turned to MIN_EXPR. */
- if (ass_code != MAX_EXPR)
- return false;
-
- minmax = MIN_EXPR;
- if (operand_equal_for_phi_arg_p (op0, smaller)
- || (alt_smaller
- && operand_equal_for_phi_arg_p (op0, alt_smaller)))
- bound = op1;
- else if (operand_equal_for_phi_arg_p (op1, smaller)
- || (alt_smaller
- && operand_equal_for_phi_arg_p (op1, alt_smaller)))
- bound = op0;
- else
- return false;
-
- /* We need BOUND <= LARGER. */
- if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node,
- bound, larger)))
- return false;
- }
- else if (operand_equal_for_phi_arg_p (arg_false, smaller)
- || (alt_smaller
- && operand_equal_for_phi_arg_p (arg_false, alt_smaller)))
- {
- /* Case
-
- if (smaller < larger)
- {
- r' = MIN_EXPR (larger, bound)
- }
- r = PHI <r', smaller> --> to be turned to MAX_EXPR. */
- if (ass_code != MIN_EXPR)
- return false;
-
- minmax = MAX_EXPR;
- if (operand_equal_for_phi_arg_p (op0, larger)
- || (alt_larger
- && operand_equal_for_phi_arg_p (op0, alt_larger)))
- bound = op1;
- else if (operand_equal_for_phi_arg_p (op1, larger)
- || (alt_larger
- && operand_equal_for_phi_arg_p (op1, alt_larger)))
- bound = op0;
- else
- return false;
-
- /* We need BOUND >= SMALLER. */
- if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node,
- bound, smaller)))
- return false;
- }
- else
- return false;
- }
- else
- {
- /* We got here if the condition is false, i.e., SMALLER > LARGER. */
- if (!operand_equal_for_phi_arg_p (lhs, arg_false))
- return false;
-
- if (operand_equal_for_phi_arg_p (arg_true, larger)
- || (alt_larger
- && operand_equal_for_phi_arg_p (arg_true, alt_larger)))
- {
- /* Case
-
- if (smaller > larger)
- {
- r' = MIN_EXPR (smaller, bound)
- }
- r = PHI <r', larger> --> to be turned to MAX_EXPR. */
- if (ass_code != MIN_EXPR)
- return false;
-
- minmax = MAX_EXPR;
- if (operand_equal_for_phi_arg_p (op0, smaller)
- || (alt_smaller
- && operand_equal_for_phi_arg_p (op0, alt_smaller)))
- bound = op1;
- else if (operand_equal_for_phi_arg_p (op1, smaller)
- || (alt_smaller
- && operand_equal_for_phi_arg_p (op1, alt_smaller)))
- bound = op0;
- else
- return false;
-
- /* We need BOUND >= LARGER. */
- if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node,
- bound, larger)))
- return false;
- }
- else if (operand_equal_for_phi_arg_p (arg_true, smaller)
- || (alt_smaller
- && operand_equal_for_phi_arg_p (arg_true, alt_smaller)))
- {
- /* Case
-
- if (smaller > larger)
- {
- r' = MAX_EXPR (larger, bound)
- }
- r = PHI <r', smaller> --> to be turned to MIN_EXPR. */
- if (ass_code != MAX_EXPR)
- return false;
-
- minmax = MIN_EXPR;
- if (operand_equal_for_phi_arg_p (op0, larger))
- bound = op1;
- else if (operand_equal_for_phi_arg_p (op1, larger))
- bound = op0;
- else
- return false;
-
- /* We need BOUND <= SMALLER. */
- if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node,
- bound, smaller)))
- return false;
- }
- else
- return false;
- }
-
- /* Move the statement from the middle block. */
- gsi = gsi_last_bb (cond_bb);
- gsi_from = gsi_last_nondebug_bb (middle_bb);
- reset_flow_sensitive_info (SINGLE_SSA_TREE_OPERAND (gsi_stmt (gsi_from),
- SSA_OP_DEF));
- gsi_move_before (&gsi_from, &gsi);
- }
-
- /* Emit the statement to compute min/max. */
- gimple_seq stmts = NULL;
- tree phi_result = PHI_RESULT (phi);
- result = gimple_build (&stmts, minmax, TREE_TYPE (phi_result), arg0, arg1);
-
- gsi = gsi_last_bb (cond_bb);
- gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT);
-
- replace_phi_edge_with_variable (cond_bb, e1, phi, result);
-
- return true;
-}
-
-/* Attempt to optimize (x <=> y) cmp 0 and similar comparisons.
- For strong ordering <=> try to match something like:
- <bb 2> : // cond3_bb (== cond2_bb)
- if (x_4(D) != y_5(D))
- goto <bb 3>; [INV]
- else
- goto <bb 6>; [INV]
-
- <bb 3> : // cond_bb
- if (x_4(D) < y_5(D))
- goto <bb 6>; [INV]
- else
- goto <bb 4>; [INV]
-
- <bb 4> : // middle_bb
-
- <bb 6> : // phi_bb
- # iftmp.0_2 = PHI <1(4), 0(2), -1(3)>
- _1 = iftmp.0_2 == 0;
-
- and for partial ordering <=> something like:
-
- <bb 2> : // cond3_bb
- if (a_3(D) == b_5(D))
- goto <bb 6>; [50.00%]
- else
- goto <bb 3>; [50.00%]
-
- <bb 3> [local count: 536870913]: // cond2_bb
- if (a_3(D) < b_5(D))
- goto <bb 6>; [50.00%]
- else
- goto <bb 4>; [50.00%]
-
- <bb 4> [local count: 268435456]: // cond_bb
- if (a_3(D) > b_5(D))
- goto <bb 6>; [50.00%]
- else
- goto <bb 5>; [50.00%]
-
- <bb 5> [local count: 134217728]: // middle_bb
-
- <bb 6> [local count: 1073741824]: // phi_bb
- # SR.27_4 = PHI <0(2), -1(3), 1(4), 2(5)>
- _2 = SR.27_4 > 0; */
-
-static bool
-spaceship_replacement (basic_block cond_bb, basic_block middle_bb,
- edge e0, edge e1, gphi *phi,
- tree arg0, tree arg1)
-{
- tree phires = PHI_RESULT (phi);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (phires))
- || TYPE_UNSIGNED (TREE_TYPE (phires))
- || !tree_fits_shwi_p (arg0)
- || !tree_fits_shwi_p (arg1)
- || !IN_RANGE (tree_to_shwi (arg0), -1, 2)
- || !IN_RANGE (tree_to_shwi (arg1), -1, 2))
- return false;
-
- basic_block phi_bb = gimple_bb (phi);
- gcc_assert (phi_bb == e0->dest && phi_bb == e1->dest);
- if (!IN_RANGE (EDGE_COUNT (phi_bb->preds), 3, 4))
- return false;
-
- use_operand_p use_p;
- gimple *use_stmt;
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (phires))
- return false;
- if (!single_imm_use (phires, &use_p, &use_stmt))
- return false;
- enum tree_code cmp;
- tree lhs, rhs;
- gimple *orig_use_stmt = use_stmt;
- tree orig_use_lhs = NULL_TREE;
- int prec = TYPE_PRECISION (TREE_TYPE (phires));
- bool is_cast = false;
-
- /* Deal with the case when match.pd has rewritten the (res & ~1) == 0
- into res <= 1 and has left a type-cast for signed types. */
- if (gimple_assign_cast_p (use_stmt))
- {
- orig_use_lhs = gimple_assign_lhs (use_stmt);
- /* match.pd would have only done this for a signed type,
- so the conversion must be to an unsigned one. */
- tree ty1 = TREE_TYPE (gimple_assign_rhs1 (use_stmt));
- tree ty2 = TREE_TYPE (orig_use_lhs);
-
- if (!TYPE_UNSIGNED (ty2) || !INTEGRAL_TYPE_P (ty2))
- return false;
- if (TYPE_PRECISION (ty1) != TYPE_PRECISION (ty2))
- return false;
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig_use_lhs))
- return false;
- if (EDGE_COUNT (phi_bb->preds) != 4)
- return false;
- if (!single_imm_use (orig_use_lhs, &use_p, &use_stmt))
- return false;
-
- is_cast = true;
- }
- else if (is_gimple_assign (use_stmt)
- && gimple_assign_rhs_code (use_stmt) == BIT_AND_EXPR
- && TREE_CODE (gimple_assign_rhs2 (use_stmt)) == INTEGER_CST
- && (wi::to_wide (gimple_assign_rhs2 (use_stmt))
- == wi::shifted_mask (1, prec - 1, false, prec)))
- {
- /* For partial_ordering result operator>= with unspec as second
- argument is (res & 1) == res, folded by match.pd into
- (res & ~1) == 0. */
- orig_use_lhs = gimple_assign_lhs (use_stmt);
- if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig_use_lhs))
- return false;
- if (EDGE_COUNT (phi_bb->preds) != 4)
- return false;
- if (!single_imm_use (orig_use_lhs, &use_p, &use_stmt))
- return false;
- }
- if (gimple_code (use_stmt) == GIMPLE_COND)
- {
- cmp = gimple_cond_code (use_stmt);
- lhs = gimple_cond_lhs (use_stmt);
- rhs = gimple_cond_rhs (use_stmt);
- }
- else if (is_gimple_assign (use_stmt))
- {
- if (gimple_assign_rhs_class (use_stmt) == GIMPLE_BINARY_RHS)
- {
- cmp = gimple_assign_rhs_code (use_stmt);
- lhs = gimple_assign_rhs1 (use_stmt);
- rhs = gimple_assign_rhs2 (use_stmt);
- }
- else if (gimple_assign_rhs_code (use_stmt) == COND_EXPR)
- {
- tree cond = gimple_assign_rhs1 (use_stmt);
- if (!COMPARISON_CLASS_P (cond))
- return false;
- cmp = TREE_CODE (cond);
- lhs = TREE_OPERAND (cond, 0);
- rhs = TREE_OPERAND (cond, 1);
- }
- else
- return false;
- }
- else
- return false;
- switch (cmp)
- {
- case EQ_EXPR:
- case NE_EXPR:
- case LT_EXPR:
- case GT_EXPR:
- case LE_EXPR:
- case GE_EXPR:
- break;
- default:
- return false;
- }
- if (lhs != (orig_use_lhs ? orig_use_lhs : phires)
- || !tree_fits_shwi_p (rhs)
- || !IN_RANGE (tree_to_shwi (rhs), -1, 1))
- return false;
-
- if (is_cast)
- {
- if (TREE_CODE (rhs) != INTEGER_CST)
- return false;
- /* As for -ffast-math we assume the 2 return to be
- impossible, canonicalize (unsigned) res <= 1U or
- (unsigned) res < 2U into res >= 0 and (unsigned) res > 1U
- or (unsigned) res >= 2U as res < 0. */
- switch (cmp)
- {
- case LE_EXPR:
- if (!integer_onep (rhs))
- return false;
- cmp = GE_EXPR;
- break;
- case LT_EXPR:
- if (wi::ne_p (wi::to_widest (rhs), 2))
- return false;
- cmp = GE_EXPR;
- break;
- case GT_EXPR:
- if (!integer_onep (rhs))
- return false;
- cmp = LT_EXPR;
- break;
- case GE_EXPR:
- if (wi::ne_p (wi::to_widest (rhs), 2))
- return false;
- cmp = LT_EXPR;
- break;
- default:
- return false;
- }
- rhs = build_zero_cst (TREE_TYPE (phires));
- }
- else if (orig_use_lhs)
- {
- if ((cmp != EQ_EXPR && cmp != NE_EXPR) || !integer_zerop (rhs))
- return false;
- /* As for -ffast-math we assume the 2 return to be
- impossible, canonicalize (res & ~1) == 0 into
- res >= 0 and (res & ~1) != 0 as res < 0. */
- cmp = cmp == EQ_EXPR ? GE_EXPR : LT_EXPR;
- }
-
- if (!empty_block_p (middle_bb))
- return false;
-
- gcond *cond1 = as_a <gcond *> (last_stmt (cond_bb));
- enum tree_code cmp1 = gimple_cond_code (cond1);
- switch (cmp1)
- {
- case LT_EXPR:
- case LE_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- break;
- default:
- return false;
- }
- tree lhs1 = gimple_cond_lhs (cond1);
- tree rhs1 = gimple_cond_rhs (cond1);
- /* The optimization may be unsafe due to NaNs. */
- if (HONOR_NANS (TREE_TYPE (lhs1)))
- return false;
- if (TREE_CODE (lhs1) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs1))
- return false;
- if (TREE_CODE (rhs1) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1))
- return false;
-
- if (!single_pred_p (cond_bb) || !cond_only_block_p (cond_bb))
- return false;
-
- basic_block cond2_bb = single_pred (cond_bb);
- if (EDGE_COUNT (cond2_bb->succs) != 2)
- return false;
- edge cond2_phi_edge;
- if (EDGE_SUCC (cond2_bb, 0)->dest == cond_bb)
- {
- if (EDGE_SUCC (cond2_bb, 1)->dest != phi_bb)
- return false;
- cond2_phi_edge = EDGE_SUCC (cond2_bb, 1);
- }
- else if (EDGE_SUCC (cond2_bb, 0)->dest != phi_bb)
- return false;
- else
- cond2_phi_edge = EDGE_SUCC (cond2_bb, 0);
- tree arg2 = gimple_phi_arg_def (phi, cond2_phi_edge->dest_idx);
- if (!tree_fits_shwi_p (arg2))
- return false;
- gimple *cond2 = last_stmt (cond2_bb);
- if (cond2 == NULL || gimple_code (cond2) != GIMPLE_COND)
- return false;
- enum tree_code cmp2 = gimple_cond_code (cond2);
- tree lhs2 = gimple_cond_lhs (cond2);
- tree rhs2 = gimple_cond_rhs (cond2);
- if (lhs2 == lhs1)
- {
- if (!operand_equal_p (rhs2, rhs1, 0))
- {
- if ((cmp2 == EQ_EXPR || cmp2 == NE_EXPR)
- && TREE_CODE (rhs1) == INTEGER_CST
- && TREE_CODE (rhs2) == INTEGER_CST)
- {
- /* For integers, we can have cond2 x == 5
- and cond1 x < 5, x <= 4, x <= 5, x < 6,
- x > 5, x >= 6, x >= 5 or x > 4. */
- if (tree_int_cst_lt (rhs1, rhs2))
- {
- if (wi::ne_p (wi::to_wide (rhs1) + 1, wi::to_wide (rhs2)))
- return false;
- if (cmp1 == LE_EXPR)
- cmp1 = LT_EXPR;
- else if (cmp1 == GT_EXPR)
- cmp1 = GE_EXPR;
- else
- return false;
- }
- else
- {
- gcc_checking_assert (tree_int_cst_lt (rhs2, rhs1));
- if (wi::ne_p (wi::to_wide (rhs2) + 1, wi::to_wide (rhs1)))
- return false;
- if (cmp1 == LT_EXPR)
- cmp1 = LE_EXPR;
- else if (cmp1 == GE_EXPR)
- cmp1 = GT_EXPR;
- else
- return false;
- }
- rhs1 = rhs2;
- }
- else
- return false;
- }
- }
- else if (lhs2 == rhs1)
- {
- if (rhs2 != lhs1)
- return false;
- }
- else
- return false;
-
- tree arg3 = arg2;
- basic_block cond3_bb = cond2_bb;
- edge cond3_phi_edge = cond2_phi_edge;
- gimple *cond3 = cond2;
- enum tree_code cmp3 = cmp2;
- tree lhs3 = lhs2;
- tree rhs3 = rhs2;
- if (EDGE_COUNT (phi_bb->preds) == 4)
- {
- if (absu_hwi (tree_to_shwi (arg2)) != 1)
- return false;
- if (e1->flags & EDGE_TRUE_VALUE)
- {
- if (tree_to_shwi (arg0) != 2
- || absu_hwi (tree_to_shwi (arg1)) != 1
- || wi::to_widest (arg1) == wi::to_widest (arg2))
- return false;
- }
- else if (tree_to_shwi (arg1) != 2
- || absu_hwi (tree_to_shwi (arg0)) != 1
- || wi::to_widest (arg0) == wi::to_widest (arg1))
- return false;
- switch (cmp2)
- {
- case LT_EXPR:
- case LE_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- break;
- default:
- return false;
- }
- /* if (x < y) goto phi_bb; else fallthru;
- if (x > y) goto phi_bb; else fallthru;
- bbx:;
- phi_bb:;
- is ok, but if x and y are swapped in one of the comparisons,
- or the comparisons are the same and operands not swapped,
- or the true and false edges are swapped, it is not. */
- if ((lhs2 == lhs1)
- ^ (((cond2_phi_edge->flags
- & ((cmp2 == LT_EXPR || cmp2 == LE_EXPR)
- ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) != 0)
- != ((e1->flags
- & ((cmp1 == LT_EXPR || cmp1 == LE_EXPR)
- ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) != 0)))
- return false;
- if (!single_pred_p (cond2_bb) || !cond_only_block_p (cond2_bb))
- return false;
- cond3_bb = single_pred (cond2_bb);
- if (EDGE_COUNT (cond2_bb->succs) != 2)
- return false;
- if (EDGE_SUCC (cond3_bb, 0)->dest == cond2_bb)
- {
- if (EDGE_SUCC (cond3_bb, 1)->dest != phi_bb)
- return false;
- cond3_phi_edge = EDGE_SUCC (cond3_bb, 1);
- }
- else if (EDGE_SUCC (cond3_bb, 0)->dest != phi_bb)
- return false;
- else
- cond3_phi_edge = EDGE_SUCC (cond3_bb, 0);
- arg3 = gimple_phi_arg_def (phi, cond3_phi_edge->dest_idx);
- cond3 = last_stmt (cond3_bb);
- if (cond3 == NULL || gimple_code (cond3) != GIMPLE_COND)
- return false;
- cmp3 = gimple_cond_code (cond3);
- lhs3 = gimple_cond_lhs (cond3);
- rhs3 = gimple_cond_rhs (cond3);
- if (lhs3 == lhs1)
- {
- if (!operand_equal_p (rhs3, rhs1, 0))
- return false;
- }
- else if (lhs3 == rhs1)
- {
- if (rhs3 != lhs1)
- return false;
- }
- else
- return false;
- }
- else if (absu_hwi (tree_to_shwi (arg0)) != 1
- || absu_hwi (tree_to_shwi (arg1)) != 1
- || wi::to_widest (arg0) == wi::to_widest (arg1))
- return false;
-
- if (!integer_zerop (arg3) || (cmp3 != EQ_EXPR && cmp3 != NE_EXPR))
- return false;
- if ((cond3_phi_edge->flags & (cmp3 == EQ_EXPR
- ? EDGE_TRUE_VALUE : EDGE_FALSE_VALUE)) == 0)
- return false;
-
- /* lhs1 one_cmp rhs1 results in phires of 1. */
- enum tree_code one_cmp;
- if ((cmp1 == LT_EXPR || cmp1 == LE_EXPR)
- ^ (!integer_onep ((e1->flags & EDGE_TRUE_VALUE) ? arg1 : arg0)))
- one_cmp = LT_EXPR;
- else
- one_cmp = GT_EXPR;
-
- enum tree_code res_cmp;
- switch (cmp)
- {
- case EQ_EXPR:
- if (integer_zerop (rhs))
- res_cmp = EQ_EXPR;
- else if (integer_minus_onep (rhs))
- res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
- else if (integer_onep (rhs))
- res_cmp = one_cmp;
- else
- return false;
- break;
- case NE_EXPR:
- if (integer_zerop (rhs))
- res_cmp = NE_EXPR;
- else if (integer_minus_onep (rhs))
- res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
- else if (integer_onep (rhs))
- res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
- else
- return false;
- break;
- case LT_EXPR:
- if (integer_onep (rhs))
- res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
- else if (integer_zerop (rhs))
- res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
- else
- return false;
- break;
- case LE_EXPR:
- if (integer_zerop (rhs))
- res_cmp = one_cmp == LT_EXPR ? GE_EXPR : LE_EXPR;
- else if (integer_minus_onep (rhs))
- res_cmp = one_cmp == LT_EXPR ? GT_EXPR : LT_EXPR;
- else
- return false;
- break;
- case GT_EXPR:
- if (integer_minus_onep (rhs))
- res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
- else if (integer_zerop (rhs))
- res_cmp = one_cmp;
- else
- return false;
- break;
- case GE_EXPR:
- if (integer_zerop (rhs))
- res_cmp = one_cmp == LT_EXPR ? LE_EXPR : GE_EXPR;
- else if (integer_onep (rhs))
- res_cmp = one_cmp;
- else
- return false;
- break;
- default:
- gcc_unreachable ();
- }
-
- if (gimple_code (use_stmt) == GIMPLE_COND)
- {
- gcond *use_cond = as_a <gcond *> (use_stmt);
- gimple_cond_set_code (use_cond, res_cmp);
- gimple_cond_set_lhs (use_cond, lhs1);
- gimple_cond_set_rhs (use_cond, rhs1);
- }
- else if (gimple_assign_rhs_class (use_stmt) == GIMPLE_BINARY_RHS)
- {
- gimple_assign_set_rhs_code (use_stmt, res_cmp);
- gimple_assign_set_rhs1 (use_stmt, lhs1);
- gimple_assign_set_rhs2 (use_stmt, rhs1);
- }
- else
- {
- tree cond = build2 (res_cmp, TREE_TYPE (gimple_assign_rhs1 (use_stmt)),
- lhs1, rhs1);
- gimple_assign_set_rhs1 (use_stmt, cond);
- }
- update_stmt (use_stmt);
-
- if (MAY_HAVE_DEBUG_BIND_STMTS)
- {
- use_operand_p use_p;
- imm_use_iterator iter;
- bool has_debug_uses = false;
- bool has_cast_debug_uses = false;
- FOR_EACH_IMM_USE_FAST (use_p, iter, phires)
- {
- gimple *use_stmt = USE_STMT (use_p);
- if (orig_use_lhs && use_stmt == orig_use_stmt)
- continue;
- gcc_assert (is_gimple_debug (use_stmt));
- has_debug_uses = true;
- break;
- }
- if (orig_use_lhs)
- {
- if (!has_debug_uses || is_cast)
- FOR_EACH_IMM_USE_FAST (use_p, iter, orig_use_lhs)
- {
- gimple *use_stmt = USE_STMT (use_p);
- gcc_assert (is_gimple_debug (use_stmt));
- has_debug_uses = true;
- if (is_cast)
- has_cast_debug_uses = true;
- }
- gimple_stmt_iterator gsi = gsi_for_stmt (orig_use_stmt);
- tree zero = build_zero_cst (TREE_TYPE (orig_use_lhs));
- gimple_assign_set_rhs_with_ops (&gsi, INTEGER_CST, zero);
- update_stmt (orig_use_stmt);
- }
-
- if (has_debug_uses)
- {
- /* If there are debug uses, emit something like:
- # DEBUG D#1 => i_2(D) > j_3(D) ? 1 : -1
- # DEBUG D#2 => i_2(D) == j_3(D) ? 0 : D#1
- where > stands for the comparison that yielded 1
- and replace debug uses of phi result with that D#2.
- Ignore the value of 2, because if NaNs aren't expected,
- all floating point numbers should be comparable. */
- gimple_stmt_iterator gsi = gsi_after_labels (gimple_bb (phi));
- tree type = TREE_TYPE (phires);
- tree temp1 = build_debug_expr_decl (type);
- tree t = build2 (one_cmp, boolean_type_node, lhs1, rhs2);
- t = build3 (COND_EXPR, type, t, build_one_cst (type),
- build_int_cst (type, -1));
- gimple *g = gimple_build_debug_bind (temp1, t, phi);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- tree temp2 = build_debug_expr_decl (type);
- t = build2 (EQ_EXPR, boolean_type_node, lhs1, rhs2);
- t = build3 (COND_EXPR, type, t, build_zero_cst (type), temp1);
- g = gimple_build_debug_bind (temp2, t, phi);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- replace_uses_by (phires, temp2);
- if (orig_use_lhs)
- {
- if (has_cast_debug_uses)
- {
- tree temp3 = make_node (DEBUG_EXPR_DECL);
- DECL_ARTIFICIAL (temp3) = 1;
- TREE_TYPE (temp3) = TREE_TYPE (orig_use_lhs);
- SET_DECL_MODE (temp3, TYPE_MODE (type));
- t = fold_convert (TREE_TYPE (temp3), temp2);
- g = gimple_build_debug_bind (temp3, t, phi);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- replace_uses_by (orig_use_lhs, temp3);
- }
- else
- replace_uses_by (orig_use_lhs, temp2);
- }
- }
- }
-
- if (orig_use_lhs)
- {
- gimple_stmt_iterator gsi = gsi_for_stmt (orig_use_stmt);
- gsi_remove (&gsi, true);
- }
-
- gimple_stmt_iterator psi = gsi_for_stmt (phi);
- remove_phi_node (&psi, true);
- statistics_counter_event (cfun, "spaceship replacement", 1);
-
- return true;
-}
-
-/* Optimize x ? __builtin_fun (x) : C, where C is __builtin_fun (0).
- Convert
-
- <bb 2>
- if (b_4(D) != 0)
- goto <bb 3>
- else
- goto <bb 4>
-
- <bb 3>
- _2 = (unsigned long) b_4(D);
- _9 = __builtin_popcountl (_2);
- OR
- _9 = __builtin_popcountl (b_4(D));
-
- <bb 4>
- c_12 = PHI <0(2), _9(3)>
-
- Into
- <bb 2>
- _2 = (unsigned long) b_4(D);
- _9 = __builtin_popcountl (_2);
- OR
- _9 = __builtin_popcountl (b_4(D));
-
- <bb 4>
- c_12 = PHI <_9(2)>
-
- Similarly for __builtin_clz or __builtin_ctz if
- C?Z_DEFINED_VALUE_AT_ZERO is 2, optab is present and
- instead of 0 above it uses the value from that macro. */
-
-static bool
-cond_removal_in_builtin_zero_pattern (basic_block cond_bb,
- basic_block middle_bb,
- edge e1, edge e2, gphi *phi,
- tree arg0, tree arg1)
-{
- gimple *cond;
- gimple_stmt_iterator gsi, gsi_from;
- gimple *call;
- gimple *cast = NULL;
- tree lhs, arg;
-
- /* Check that
- _2 = (unsigned long) b_4(D);
- _9 = __builtin_popcountl (_2);
- OR
- _9 = __builtin_popcountl (b_4(D));
- are the only stmts in the middle_bb. */
-
- gsi = gsi_start_nondebug_after_labels_bb (middle_bb);
- if (gsi_end_p (gsi))
- return false;
- cast = gsi_stmt (gsi);
- gsi_next_nondebug (&gsi);
- if (!gsi_end_p (gsi))
- {
- call = gsi_stmt (gsi);
- gsi_next_nondebug (&gsi);
- if (!gsi_end_p (gsi))
- return false;
- }
- else
- {
- call = cast;
- cast = NULL;
- }
-
- /* Check that we have a popcount/clz/ctz builtin. */
- if (!is_gimple_call (call) || gimple_call_num_args (call) != 1)
- return false;
-
- arg = gimple_call_arg (call, 0);
- lhs = gimple_get_lhs (call);
-
- if (lhs == NULL_TREE)
- return false;
-
- combined_fn cfn = gimple_call_combined_fn (call);
- internal_fn ifn = IFN_LAST;
- int val = 0;
- switch (cfn)
- {
- case CFN_BUILT_IN_BSWAP16:
- case CFN_BUILT_IN_BSWAP32:
- case CFN_BUILT_IN_BSWAP64:
- case CFN_BUILT_IN_BSWAP128:
- CASE_CFN_FFS:
- CASE_CFN_PARITY:
- CASE_CFN_POPCOUNT:
- break;
- CASE_CFN_CLZ:
- if (INTEGRAL_TYPE_P (TREE_TYPE (arg)))
- {
- tree type = TREE_TYPE (arg);
- if (direct_internal_fn_supported_p (IFN_CLZ, type, OPTIMIZE_FOR_BOTH)
- && CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (type),
- val) == 2)
- {
- ifn = IFN_CLZ;
- break;
- }
- }
- return false;
- CASE_CFN_CTZ:
- if (INTEGRAL_TYPE_P (TREE_TYPE (arg)))
- {
- tree type = TREE_TYPE (arg);
- if (direct_internal_fn_supported_p (IFN_CTZ, type, OPTIMIZE_FOR_BOTH)
- && CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (type),
- val) == 2)
- {
- ifn = IFN_CTZ;
- break;
- }
- }
- return false;
- case CFN_BUILT_IN_CLRSB:
- val = TYPE_PRECISION (integer_type_node) - 1;
- break;
- case CFN_BUILT_IN_CLRSBL:
- val = TYPE_PRECISION (long_integer_type_node) - 1;
- break;
- case CFN_BUILT_IN_CLRSBLL:
- val = TYPE_PRECISION (long_long_integer_type_node) - 1;
- break;
- default:
- return false;
- }
-
- if (cast)
- {
- /* We have a cast stmt feeding popcount/clz/ctz builtin. */
- /* Check that we have a cast prior to that. */
- if (gimple_code (cast) != GIMPLE_ASSIGN
- || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (cast)))
- return false;
- /* Result of the cast stmt is the argument to the builtin. */
- if (arg != gimple_assign_lhs (cast))
- return false;
- arg = gimple_assign_rhs1 (cast);
- }
-
- cond = last_stmt (cond_bb);
-
- /* Cond_bb has a check for b_4 [!=|==] 0 before calling the popcount/clz/ctz
- builtin. */
- if (gimple_code (cond) != GIMPLE_COND
- || (gimple_cond_code (cond) != NE_EXPR
- && gimple_cond_code (cond) != EQ_EXPR)
- || !integer_zerop (gimple_cond_rhs (cond))
- || arg != gimple_cond_lhs (cond))
- return false;
-
- /* Canonicalize. */
- if ((e2->flags & EDGE_TRUE_VALUE
- && gimple_cond_code (cond) == NE_EXPR)
- || (e1->flags & EDGE_TRUE_VALUE
- && gimple_cond_code (cond) == EQ_EXPR))
- {
- std::swap (arg0, arg1);
- std::swap (e1, e2);
- }
-
- /* Check PHI arguments. */
- if (lhs != arg0
- || TREE_CODE (arg1) != INTEGER_CST
- || wi::to_wide (arg1) != val)
- return false;
-
- /* And insert the popcount/clz/ctz builtin and cast stmt before the
- cond_bb. */
- gsi = gsi_last_bb (cond_bb);
- if (cast)
- {
- gsi_from = gsi_for_stmt (cast);
- gsi_move_before (&gsi_from, &gsi);
- reset_flow_sensitive_info (gimple_get_lhs (cast));
- }
- gsi_from = gsi_for_stmt (call);
- if (ifn == IFN_LAST || gimple_call_internal_p (call))
- gsi_move_before (&gsi_from, &gsi);
- else
- {
- /* For __builtin_c[lt]z* force .C[LT]Z ifn, because only
- the latter is well defined at zero. */
- call = gimple_build_call_internal (ifn, 1, gimple_call_arg (call, 0));
- gimple_call_set_lhs (call, lhs);
- gsi_insert_before (&gsi, call, GSI_SAME_STMT);
- gsi_remove (&gsi_from, true);
- }
- reset_flow_sensitive_info (lhs);
-
- /* Now update the PHI and remove unneeded bbs. */
- replace_phi_edge_with_variable (cond_bb, e2, phi, lhs);
- return true;
-}
-
-/* Auxiliary functions to determine the set of memory accesses which
- can't trap because they are preceded by accesses to the same memory
- portion. We do that for MEM_REFs, so we only need to track
- the SSA_NAME of the pointer indirectly referenced. The algorithm
- simply is a walk over all instructions in dominator order. When
- we see an MEM_REF we determine if we've already seen a same
- ref anywhere up to the root of the dominator tree. If we do the
- current access can't trap. If we don't see any dominating access
- the current access might trap, but might also make later accesses
- non-trapping, so we remember it. We need to be careful with loads
- or stores, for instance a load might not trap, while a store would,
- so if we see a dominating read access this doesn't mean that a later
- write access would not trap. Hence we also need to differentiate the
- type of access(es) seen.
-
- ??? We currently are very conservative and assume that a load might
- trap even if a store doesn't (write-only memory). This probably is
- overly conservative.
-
- We currently support a special case that for !TREE_ADDRESSABLE automatic
- variables, it could ignore whether something is a load or store because the
- local stack should be always writable. */
-
-/* A hash-table of references (MEM_REF/ARRAY_REF/COMPONENT_REF), and in which
- basic block an *_REF through it was seen, which would constitute a
- no-trap region for same accesses.
-
- Size is needed to support 2 MEM_REFs of different types, like
- MEM<double>(s_1) and MEM<long>(s_1), which would compare equal with
- OEP_ADDRESS_OF. */
-struct ref_to_bb
-{
- tree exp;
- HOST_WIDE_INT size;
- unsigned int phase;
- basic_block bb;
-};
-
-/* Hashtable helpers. */
-
-struct refs_hasher : free_ptr_hash<ref_to_bb>
-{
- static inline hashval_t hash (const ref_to_bb *);
- static inline bool equal (const ref_to_bb *, const ref_to_bb *);
-};
-
-/* Used for quick clearing of the hash-table when we see calls.
- Hash entries with phase < nt_call_phase are invalid. */
-static unsigned int nt_call_phase;
-
-/* The hash function. */
-
-inline hashval_t
-refs_hasher::hash (const ref_to_bb *n)
-{
- inchash::hash hstate;
- inchash::add_expr (n->exp, hstate, OEP_ADDRESS_OF);
- hstate.add_hwi (n->size);
- return hstate.end ();
-}
-
-/* The equality function of *P1 and *P2. */
-
-inline bool
-refs_hasher::equal (const ref_to_bb *n1, const ref_to_bb *n2)
-{
- return operand_equal_p (n1->exp, n2->exp, OEP_ADDRESS_OF)
- && n1->size == n2->size;
-}
-
-class nontrapping_dom_walker : public dom_walker
-{
-public:
- nontrapping_dom_walker (cdi_direction direction, hash_set<tree> *ps)
- : dom_walker (direction), m_nontrapping (ps), m_seen_refs (128)
- {}
-
- virtual edge before_dom_children (basic_block);
- virtual void after_dom_children (basic_block);
-
-private:
-
- /* We see the expression EXP in basic block BB. If it's an interesting
- expression (an MEM_REF through an SSA_NAME) possibly insert the
- expression into the set NONTRAP or the hash table of seen expressions.
- STORE is true if this expression is on the LHS, otherwise it's on
- the RHS. */
- void add_or_mark_expr (basic_block, tree, bool);
-
- hash_set<tree> *m_nontrapping;
-
- /* The hash table for remembering what we've seen. */
- hash_table<refs_hasher> m_seen_refs;
-};
-
-/* Called by walk_dominator_tree, when entering the block BB. */
-edge
-nontrapping_dom_walker::before_dom_children (basic_block bb)
-{
- edge e;
- edge_iterator ei;
- gimple_stmt_iterator gsi;
-
- /* If we haven't seen all our predecessors, clear the hash-table. */
- FOR_EACH_EDGE (e, ei, bb->preds)
- if ((((size_t)e->src->aux) & 2) == 0)
- {
- nt_call_phase++;
- break;
- }
-
- /* Mark this BB as being on the path to dominator root and as visited. */
- bb->aux = (void*)(1 | 2);
-
- /* And walk the statements in order. */
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
-
- if ((gimple_code (stmt) == GIMPLE_ASM && gimple_vdef (stmt))
- || (is_gimple_call (stmt)
- && (!nonfreeing_call_p (stmt) || !nonbarrier_call_p (stmt))))
- nt_call_phase++;
- else if (gimple_assign_single_p (stmt) && !gimple_has_volatile_ops (stmt))
- {
- add_or_mark_expr (bb, gimple_assign_lhs (stmt), true);
- add_or_mark_expr (bb, gimple_assign_rhs1 (stmt), false);
- }
- }
- return NULL;
-}
-
-/* Called by walk_dominator_tree, when basic block BB is exited. */
-void
-nontrapping_dom_walker::after_dom_children (basic_block bb)
-{
- /* This BB isn't on the path to dominator root anymore. */
- bb->aux = (void*)2;
-}
-
-/* We see the expression EXP in basic block BB. If it's an interesting
- expression of:
- 1) MEM_REF
- 2) ARRAY_REF
- 3) COMPONENT_REF
- possibly insert the expression into the set NONTRAP or the hash table
- of seen expressions. STORE is true if this expression is on the LHS,
- otherwise it's on the RHS. */
-void
-nontrapping_dom_walker::add_or_mark_expr (basic_block bb, tree exp, bool store)
-{
- HOST_WIDE_INT size;
-
- if ((TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == ARRAY_REF
- || TREE_CODE (exp) == COMPONENT_REF)
- && (size = int_size_in_bytes (TREE_TYPE (exp))) > 0)
- {
- struct ref_to_bb map;
- ref_to_bb **slot;
- struct ref_to_bb *r2bb;
- basic_block found_bb = 0;
-
- if (!store)
- {
- tree base = get_base_address (exp);
- /* Only record a LOAD of a local variable without address-taken, as
- the local stack is always writable. This allows cselim on a STORE
- with a dominating LOAD. */
- if (!auto_var_p (base) || TREE_ADDRESSABLE (base))
- return;
- }
-
- /* Try to find the last seen *_REF, which can trap. */
- map.exp = exp;
- map.size = size;
- slot = m_seen_refs.find_slot (&map, INSERT);
- r2bb = *slot;
- if (r2bb && r2bb->phase >= nt_call_phase)
- found_bb = r2bb->bb;
-
- /* If we've found a trapping *_REF, _and_ it dominates EXP
- (it's in a basic block on the path from us to the dominator root)
- then we can't trap. */
- if (found_bb && (((size_t)found_bb->aux) & 1) == 1)
- {
- m_nontrapping->add (exp);
- }
- else
- {
- /* EXP might trap, so insert it into the hash table. */
- if (r2bb)
- {
- r2bb->phase = nt_call_phase;
- r2bb->bb = bb;
- }
- else
- {
- r2bb = XNEW (struct ref_to_bb);
- r2bb->phase = nt_call_phase;
- r2bb->bb = bb;
- r2bb->exp = exp;
- r2bb->size = size;
- *slot = r2bb;
- }
- }
- }
-}
-
-/* This is the entry point of gathering non trapping memory accesses.
- It will do a dominator walk over the whole function, and it will
- make use of the bb->aux pointers. It returns a set of trees
- (the MEM_REFs itself) which can't trap. */
-static hash_set<tree> *
-get_non_trapping (void)
-{
- nt_call_phase = 0;
- hash_set<tree> *nontrap = new hash_set<tree>;
-
- nontrapping_dom_walker (CDI_DOMINATORS, nontrap)
- .walk (cfun->cfg->x_entry_block_ptr);
-
- clear_aux_for_blocks ();
- return nontrap;
-}
-
-/* Do the main work of conditional store replacement. We already know
- that the recognized pattern looks like so:
-
- split:
- if (cond) goto MIDDLE_BB; else goto JOIN_BB (edge E1)
- MIDDLE_BB:
- something
- fallthrough (edge E0)
- JOIN_BB:
- some more
-
- We check that MIDDLE_BB contains only one store, that that store
- doesn't trap (not via NOTRAP, but via checking if an access to the same
- memory location dominates us, or the store is to a local addressable
- object) and that the store has a "simple" RHS. */
-
-static bool
-cond_store_replacement (basic_block middle_bb, basic_block join_bb,
- edge e0, edge e1, hash_set<tree> *nontrap)
-{
- gimple *assign = last_and_only_stmt (middle_bb);
- tree lhs, rhs, name, name2;
- gphi *newphi;
- gassign *new_stmt;
- gimple_stmt_iterator gsi;
- location_t locus;
-
- /* Check if middle_bb contains of only one store. */
- if (!assign
- || !gimple_assign_single_p (assign)
- || gimple_has_volatile_ops (assign))
- return false;
-
- /* And no PHI nodes so all uses in the single stmt are also
- available where we insert to. */
- if (!gimple_seq_empty_p (phi_nodes (middle_bb)))
- return false;
-
- locus = gimple_location (assign);
- lhs = gimple_assign_lhs (assign);
- rhs = gimple_assign_rhs1 (assign);
- if ((!REFERENCE_CLASS_P (lhs)
- && !DECL_P (lhs))
- || !is_gimple_reg_type (TREE_TYPE (lhs)))
- return false;
-
- /* Prove that we can move the store down. We could also check
- TREE_THIS_NOTRAP here, but in that case we also could move stores,
- whose value is not available readily, which we want to avoid. */
- if (!nontrap->contains (lhs))
- {
- /* If LHS is an access to a local variable without address-taken
- (or when we allow data races) and known not to trap, we could
- always safely move down the store. */
- tree base = get_base_address (lhs);
- if (!auto_var_p (base)
- || (TREE_ADDRESSABLE (base) && !flag_store_data_races)
- || tree_could_trap_p (lhs))
- return false;
- }
-
- /* Now we've checked the constraints, so do the transformation:
- 1) Remove the single store. */
- gsi = gsi_for_stmt (assign);
- unlink_stmt_vdef (assign);
- gsi_remove (&gsi, true);
- release_defs (assign);
-
- /* Make both store and load use alias-set zero as we have to
- deal with the case of the store being a conditional change
- of the dynamic type. */
- lhs = unshare_expr (lhs);
- tree *basep = &lhs;
- while (handled_component_p (*basep))
- basep = &TREE_OPERAND (*basep, 0);
- if (TREE_CODE (*basep) == MEM_REF
- || TREE_CODE (*basep) == TARGET_MEM_REF)
- TREE_OPERAND (*basep, 1)
- = fold_convert (ptr_type_node, TREE_OPERAND (*basep, 1));
- else
- *basep = build2 (MEM_REF, TREE_TYPE (*basep),
- build_fold_addr_expr (*basep),
- build_zero_cst (ptr_type_node));
-
- /* 2) Insert a load from the memory of the store to the temporary
- on the edge which did not contain the store. */
- name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore");
- new_stmt = gimple_build_assign (name, lhs);
- gimple_set_location (new_stmt, locus);
- lhs = unshare_expr (lhs);
- {
- /* Set the no-warning bit on the rhs of the load to avoid uninit
- warnings. */
- tree rhs1 = gimple_assign_rhs1 (new_stmt);
- suppress_warning (rhs1, OPT_Wuninitialized);
- }
- gsi_insert_on_edge (e1, new_stmt);
-
- /* 3) Create a PHI node at the join block, with one argument
- holding the old RHS, and the other holding the temporary
- where we stored the old memory contents. */
- name2 = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore");
- newphi = create_phi_node (name2, join_bb);
- add_phi_arg (newphi, rhs, e0, locus);
- add_phi_arg (newphi, name, e1, locus);
-
- new_stmt = gimple_build_assign (lhs, PHI_RESULT (newphi));
-
- /* 4) Insert that PHI node. */
- gsi = gsi_after_labels (join_bb);
- if (gsi_end_p (gsi))
- {
- gsi = gsi_last_bb (join_bb);
- gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT);
- }
- else
- gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "\nConditional store replacement happened!");
- fprintf (dump_file, "\nReplaced the store with a load.");
- fprintf (dump_file, "\nInserted a new PHI statement in joint block:\n");
- print_gimple_stmt (dump_file, new_stmt, 0, TDF_VOPS|TDF_MEMSYMS);
- }
- statistics_counter_event (cfun, "conditional store replacement", 1);
-
- return true;
-}
-
-/* Do the main work of conditional store replacement. */
-
-static bool
-cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb,
- basic_block join_bb, gimple *then_assign,
- gimple *else_assign)
-{
- tree lhs_base, lhs, then_rhs, else_rhs, name;
- location_t then_locus, else_locus;
- gimple_stmt_iterator gsi;
- gphi *newphi;
- gassign *new_stmt;
-
- if (then_assign == NULL
- || !gimple_assign_single_p (then_assign)
- || gimple_clobber_p (then_assign)
- || gimple_has_volatile_ops (then_assign)
- || else_assign == NULL
- || !gimple_assign_single_p (else_assign)
- || gimple_clobber_p (else_assign)
- || gimple_has_volatile_ops (else_assign))
- return false;
-
- lhs = gimple_assign_lhs (then_assign);
- if (!is_gimple_reg_type (TREE_TYPE (lhs))
- || !operand_equal_p (lhs, gimple_assign_lhs (else_assign), 0))
- return false;
-
- lhs_base = get_base_address (lhs);
- if (lhs_base == NULL_TREE
- || (!DECL_P (lhs_base) && TREE_CODE (lhs_base) != MEM_REF))
- return false;
-
- then_rhs = gimple_assign_rhs1 (then_assign);
- else_rhs = gimple_assign_rhs1 (else_assign);
- then_locus = gimple_location (then_assign);
- else_locus = gimple_location (else_assign);
-
- /* Now we've checked the constraints, so do the transformation:
- 1) Remove the stores. */
- gsi = gsi_for_stmt (then_assign);
- unlink_stmt_vdef (then_assign);
- gsi_remove (&gsi, true);
- release_defs (then_assign);
-
- gsi = gsi_for_stmt (else_assign);
- unlink_stmt_vdef (else_assign);
- gsi_remove (&gsi, true);
- release_defs (else_assign);
-
- /* 2) Create a PHI node at the join block, with one argument
- holding the old RHS, and the other holding the temporary
- where we stored the old memory contents. */
- name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore");
- newphi = create_phi_node (name, join_bb);
- add_phi_arg (newphi, then_rhs, EDGE_SUCC (then_bb, 0), then_locus);
- add_phi_arg (newphi, else_rhs, EDGE_SUCC (else_bb, 0), else_locus);
-
- new_stmt = gimple_build_assign (lhs, PHI_RESULT (newphi));
-
- /* 3) Insert that PHI node. */
- gsi = gsi_after_labels (join_bb);
- if (gsi_end_p (gsi))
- {
- gsi = gsi_last_bb (join_bb);
- gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT);
- }
- else
- gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
-
- statistics_counter_event (cfun, "if-then-else store replacement", 1);
-
- return true;
-}
-
-/* Return the single store in BB with VDEF or NULL if there are
- other stores in the BB or loads following the store. */
-
-static gimple *
-single_trailing_store_in_bb (basic_block bb, tree vdef)
-{
- if (SSA_NAME_IS_DEFAULT_DEF (vdef))
- return NULL;
- gimple *store = SSA_NAME_DEF_STMT (vdef);
- if (gimple_bb (store) != bb
- || gimple_code (store) == GIMPLE_PHI)
- return NULL;
-
- /* Verify there is no other store in this BB. */
- if (!SSA_NAME_IS_DEFAULT_DEF (gimple_vuse (store))
- && gimple_bb (SSA_NAME_DEF_STMT (gimple_vuse (store))) == bb
- && gimple_code (SSA_NAME_DEF_STMT (gimple_vuse (store))) != GIMPLE_PHI)
- return NULL;
-
- /* Verify there is no load or store after the store. */
- use_operand_p use_p;
- imm_use_iterator imm_iter;
- FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_vdef (store))
- if (USE_STMT (use_p) != store
- && gimple_bb (USE_STMT (use_p)) == bb)
- return NULL;
-
- return store;
-}
-
-/* Conditional store replacement. We already know
- that the recognized pattern looks like so:
-
- split:
- if (cond) goto THEN_BB; else goto ELSE_BB (edge E1)
- THEN_BB:
- ...
- X = Y;
- ...
- goto JOIN_BB;
- ELSE_BB:
- ...
- X = Z;
- ...
- fallthrough (edge E0)
- JOIN_BB:
- some more
-
- We check that it is safe to sink the store to JOIN_BB by verifying that
- there are no read-after-write or write-after-write dependencies in
- THEN_BB and ELSE_BB. */
-
-static bool
-cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb,
- basic_block join_bb)
-{
- vec<data_reference_p> then_datarefs, else_datarefs;
- vec<ddr_p> then_ddrs, else_ddrs;
- gimple *then_store, *else_store;
- bool found, ok = false, res;
- struct data_dependence_relation *ddr;
- data_reference_p then_dr, else_dr;
- int i, j;
- tree then_lhs, else_lhs;
- basic_block blocks[3];
-
- /* Handle the case with single store in THEN_BB and ELSE_BB. That is
- cheap enough to always handle as it allows us to elide dependence
- checking. */
- gphi *vphi = NULL;
- for (gphi_iterator si = gsi_start_phis (join_bb); !gsi_end_p (si);
- gsi_next (&si))
- if (virtual_operand_p (gimple_phi_result (si.phi ())))
- {
- vphi = si.phi ();
- break;
- }
- if (!vphi)
- return false;
- tree then_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (then_bb));
- tree else_vdef = PHI_ARG_DEF_FROM_EDGE (vphi, single_succ_edge (else_bb));
- gimple *then_assign = single_trailing_store_in_bb (then_bb, then_vdef);
- if (then_assign)
- {
- gimple *else_assign = single_trailing_store_in_bb (else_bb, else_vdef);
- if (else_assign)
- return cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
- then_assign, else_assign);
- }
-
- /* If either vectorization or if-conversion is disabled then do
- not sink any stores. */
- if (param_max_stores_to_sink == 0
- || (!flag_tree_loop_vectorize && !flag_tree_slp_vectorize)
- || !flag_tree_loop_if_convert)
- return false;
-
- /* Find data references. */
- then_datarefs.create (1);
- else_datarefs.create (1);
- if ((find_data_references_in_bb (NULL, then_bb, &then_datarefs)
- == chrec_dont_know)
- || !then_datarefs.length ()
- || (find_data_references_in_bb (NULL, else_bb, &else_datarefs)
- == chrec_dont_know)
- || !else_datarefs.length ())
- {
- free_data_refs (then_datarefs);
- free_data_refs (else_datarefs);
- return false;
- }
-
- /* Find pairs of stores with equal LHS. */
- auto_vec<gimple *, 1> then_stores, else_stores;
- FOR_EACH_VEC_ELT (then_datarefs, i, then_dr)
- {
- if (DR_IS_READ (then_dr))
- continue;
-
- then_store = DR_STMT (then_dr);
- then_lhs = gimple_get_lhs (then_store);
- if (then_lhs == NULL_TREE)
- continue;
- found = false;
-
- FOR_EACH_VEC_ELT (else_datarefs, j, else_dr)
- {
- if (DR_IS_READ (else_dr))
- continue;
-
- else_store = DR_STMT (else_dr);
- else_lhs = gimple_get_lhs (else_store);
- if (else_lhs == NULL_TREE)
- continue;
-
- if (operand_equal_p (then_lhs, else_lhs, 0))
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- continue;
-
- then_stores.safe_push (then_store);
- else_stores.safe_push (else_store);
- }
-
- /* No pairs of stores found. */
- if (!then_stores.length ()
- || then_stores.length () > (unsigned) param_max_stores_to_sink)
- {
- free_data_refs (then_datarefs);
- free_data_refs (else_datarefs);
- return false;
- }
-
- /* Compute and check data dependencies in both basic blocks. */
- then_ddrs.create (1);
- else_ddrs.create (1);
- if (!compute_all_dependences (then_datarefs, &then_ddrs,
- vNULL, false)
- || !compute_all_dependences (else_datarefs, &else_ddrs,
- vNULL, false))
- {
- free_dependence_relations (then_ddrs);
- free_dependence_relations (else_ddrs);
- free_data_refs (then_datarefs);
- free_data_refs (else_datarefs);
- return false;
- }
- blocks[0] = then_bb;
- blocks[1] = else_bb;
- blocks[2] = join_bb;
- renumber_gimple_stmt_uids_in_blocks (blocks, 3);
-
- /* Check that there are no read-after-write or write-after-write dependencies
- in THEN_BB. */
- FOR_EACH_VEC_ELT (then_ddrs, i, ddr)
- {
- struct data_reference *dra = DDR_A (ddr);
- struct data_reference *drb = DDR_B (ddr);
-
- if (DDR_ARE_DEPENDENT (ddr) != chrec_known
- && ((DR_IS_READ (dra) && DR_IS_WRITE (drb)
- && gimple_uid (DR_STMT (dra)) > gimple_uid (DR_STMT (drb)))
- || (DR_IS_READ (drb) && DR_IS_WRITE (dra)
- && gimple_uid (DR_STMT (drb)) > gimple_uid (DR_STMT (dra)))
- || (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))))
- {
- free_dependence_relations (then_ddrs);
- free_dependence_relations (else_ddrs);
- free_data_refs (then_datarefs);
- free_data_refs (else_datarefs);
- return false;
- }
- }
-
- /* Check that there are no read-after-write or write-after-write dependencies
- in ELSE_BB. */
- FOR_EACH_VEC_ELT (else_ddrs, i, ddr)
- {
- struct data_reference *dra = DDR_A (ddr);
- struct data_reference *drb = DDR_B (ddr);
-
- if (DDR_ARE_DEPENDENT (ddr) != chrec_known
- && ((DR_IS_READ (dra) && DR_IS_WRITE (drb)
- && gimple_uid (DR_STMT (dra)) > gimple_uid (DR_STMT (drb)))
- || (DR_IS_READ (drb) && DR_IS_WRITE (dra)
- && gimple_uid (DR_STMT (drb)) > gimple_uid (DR_STMT (dra)))
- || (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))))
- {
- free_dependence_relations (then_ddrs);
- free_dependence_relations (else_ddrs);
- free_data_refs (then_datarefs);
- free_data_refs (else_datarefs);
- return false;
- }
- }
-
- /* Sink stores with same LHS. */
- FOR_EACH_VEC_ELT (then_stores, i, then_store)
- {
- else_store = else_stores[i];
- res = cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb,
- then_store, else_store);
- ok = ok || res;
- }
-
- free_dependence_relations (then_ddrs);
- free_dependence_relations (else_ddrs);
- free_data_refs (then_datarefs);
- free_data_refs (else_datarefs);
-
- return ok;
-}
-
-/* Return TRUE if STMT has a VUSE whose corresponding VDEF is in BB. */
-
-static bool
-local_mem_dependence (gimple *stmt, basic_block bb)
-{
- tree vuse = gimple_vuse (stmt);
- gimple *def;
-
- if (!vuse)
- return false;
-
- def = SSA_NAME_DEF_STMT (vuse);
- return (def && gimple_bb (def) == bb);
-}
-
-/* Given a "diamond" control-flow pattern where BB0 tests a condition,
- BB1 and BB2 are "then" and "else" blocks dependent on this test,
- and BB3 rejoins control flow following BB1 and BB2, look for
- opportunities to hoist loads as follows. If BB3 contains a PHI of
- two loads, one each occurring in BB1 and BB2, and the loads are
- provably of adjacent fields in the same structure, then move both
- loads into BB0. Of course this can only be done if there are no
- dependencies preventing such motion.
-
- One of the hoisted loads will always be speculative, so the
- transformation is currently conservative:
-
- - The fields must be strictly adjacent.
- - The two fields must occupy a single memory block that is
- guaranteed to not cross a page boundary.
-
- The last is difficult to prove, as such memory blocks should be
- aligned on the minimum of the stack alignment boundary and the
- alignment guaranteed by heap allocation interfaces. Thus we rely
- on a parameter for the alignment value.
-
- Provided a good value is used for the last case, the first
- restriction could possibly be relaxed. */
-
-static void
-hoist_adjacent_loads (basic_block bb0, basic_block bb1,
- basic_block bb2, basic_block bb3)
-{
- int param_align = param_l1_cache_line_size;
- unsigned param_align_bits = (unsigned) (param_align * BITS_PER_UNIT);
- gphi_iterator gsi;
-
- /* Walk the phis in bb3 looking for an opportunity. We are looking
- for phis of two SSA names, one each of which is defined in bb1 and
- bb2. */
- for (gsi = gsi_start_phis (bb3); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- gphi *phi_stmt = gsi.phi ();
- gimple *def1, *def2;
- tree arg1, arg2, ref1, ref2, field1, field2;
- tree tree_offset1, tree_offset2, tree_size2, next;
- int offset1, offset2, size2;
- unsigned align1;
- gimple_stmt_iterator gsi2;
- basic_block bb_for_def1, bb_for_def2;
-
- if (gimple_phi_num_args (phi_stmt) != 2
- || virtual_operand_p (gimple_phi_result (phi_stmt)))
- continue;
-
- arg1 = gimple_phi_arg_def (phi_stmt, 0);
- arg2 = gimple_phi_arg_def (phi_stmt, 1);
-
- if (TREE_CODE (arg1) != SSA_NAME
- || TREE_CODE (arg2) != SSA_NAME
- || SSA_NAME_IS_DEFAULT_DEF (arg1)
- || SSA_NAME_IS_DEFAULT_DEF (arg2))
- continue;
-
- def1 = SSA_NAME_DEF_STMT (arg1);
- def2 = SSA_NAME_DEF_STMT (arg2);
-
- if ((gimple_bb (def1) != bb1 || gimple_bb (def2) != bb2)
- && (gimple_bb (def2) != bb1 || gimple_bb (def1) != bb2))
- continue;
-
- /* Check the mode of the arguments to be sure a conditional move
- can be generated for it. */
- if (optab_handler (movcc_optab, TYPE_MODE (TREE_TYPE (arg1)))
- == CODE_FOR_nothing)
- continue;
-
- /* Both statements must be assignments whose RHS is a COMPONENT_REF. */
- if (!gimple_assign_single_p (def1)
- || !gimple_assign_single_p (def2)
- || gimple_has_volatile_ops (def1)
- || gimple_has_volatile_ops (def2))
- continue;
-
- ref1 = gimple_assign_rhs1 (def1);
- ref2 = gimple_assign_rhs1 (def2);
-
- if (TREE_CODE (ref1) != COMPONENT_REF
- || TREE_CODE (ref2) != COMPONENT_REF)
- continue;
-
- /* The zeroth operand of the two component references must be
- identical. It is not sufficient to compare get_base_address of
- the two references, because this could allow for different
- elements of the same array in the two trees. It is not safe to
- assume that the existence of one array element implies the
- existence of a different one. */
- if (!operand_equal_p (TREE_OPERAND (ref1, 0), TREE_OPERAND (ref2, 0), 0))
- continue;
-
- field1 = TREE_OPERAND (ref1, 1);
- field2 = TREE_OPERAND (ref2, 1);
-
- /* Check for field adjacency, and ensure field1 comes first. */
- for (next = DECL_CHAIN (field1);
- next && TREE_CODE (next) != FIELD_DECL;
- next = DECL_CHAIN (next))
- ;
-
- if (next != field2)
- {
- for (next = DECL_CHAIN (field2);
- next && TREE_CODE (next) != FIELD_DECL;
- next = DECL_CHAIN (next))
- ;
-
- if (next != field1)
- continue;
-
- std::swap (field1, field2);
- std::swap (def1, def2);
- }
-
- bb_for_def1 = gimple_bb (def1);
- bb_for_def2 = gimple_bb (def2);
-
- /* Check for proper alignment of the first field. */
- tree_offset1 = bit_position (field1);
- tree_offset2 = bit_position (field2);
- tree_size2 = DECL_SIZE (field2);
-
- if (!tree_fits_uhwi_p (tree_offset1)
- || !tree_fits_uhwi_p (tree_offset2)
- || !tree_fits_uhwi_p (tree_size2))
- continue;
-
- offset1 = tree_to_uhwi (tree_offset1);
- offset2 = tree_to_uhwi (tree_offset2);
- size2 = tree_to_uhwi (tree_size2);
- align1 = DECL_ALIGN (field1) % param_align_bits;
-
- if (offset1 % BITS_PER_UNIT != 0)
- continue;
-
- /* For profitability, the two field references should fit within
- a single cache line. */
- if (align1 + offset2 - offset1 + size2 > param_align_bits)
- continue;
-
- /* The two expressions cannot be dependent upon vdefs defined
- in bb1/bb2. */
- if (local_mem_dependence (def1, bb_for_def1)
- || local_mem_dependence (def2, bb_for_def2))
- continue;
-
- /* The conditions are satisfied; hoist the loads from bb1 and bb2 into
- bb0. We hoist the first one first so that a cache miss is handled
- efficiently regardless of hardware cache-fill policy. */
- gsi2 = gsi_for_stmt (def1);
- gsi_move_to_bb_end (&gsi2, bb0);
- gsi2 = gsi_for_stmt (def2);
- gsi_move_to_bb_end (&gsi2, bb0);
- statistics_counter_event (cfun, "hoisted loads", 1);
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file,
- "\nHoisting adjacent loads from %d and %d into %d: \n",
- bb_for_def1->index, bb_for_def2->index, bb0->index);
- print_gimple_stmt (dump_file, def1, 0, TDF_VOPS|TDF_MEMSYMS);
- print_gimple_stmt (dump_file, def2, 0, TDF_VOPS|TDF_MEMSYMS);
- }
- }
-}
-
-/* Determine whether we should attempt to hoist adjacent loads out of
- diamond patterns in pass_phiopt. Always hoist loads if
- -fhoist-adjacent-loads is specified and the target machine has
- both a conditional move instruction and a defined cache line size. */
-
-static bool
-gate_hoist_loads (void)
-{
- return (flag_hoist_adjacent_loads == 1
- && param_l1_cache_line_size
- && HAVE_conditional_move);
-}
-
-/* This pass tries to replaces an if-then-else block with an
- assignment. We have four kinds of transformations. Some of these
- transformations are also performed by the ifcvt RTL optimizer.
-
- Conditional Replacement
- -----------------------
-
- This transformation, implemented in match_simplify_replacement,
- replaces
-
- bb0:
- if (cond) goto bb2; else goto bb1;
- bb1:
- bb2:
- x = PHI <0 (bb1), 1 (bb0), ...>;
-
- with
-
- bb0:
- x' = cond;
- goto bb2;
- bb2:
- x = PHI <x' (bb0), ...>;
-
- We remove bb1 as it becomes unreachable. This occurs often due to
- gimplification of conditionals.
-
- Value Replacement
- -----------------
-
- This transformation, implemented in value_replacement, replaces
-
- bb0:
- if (a != b) goto bb2; else goto bb1;
- bb1:
- bb2:
- x = PHI <a (bb1), b (bb0), ...>;
-
- with
-
- bb0:
- bb2:
- x = PHI <b (bb0), ...>;
-
- This opportunity can sometimes occur as a result of other
- optimizations.
-
-
- Another case caught by value replacement looks like this:
-
- bb0:
- t1 = a == CONST;
- t2 = b > c;
- t3 = t1 & t2;
- if (t3 != 0) goto bb1; else goto bb2;
- bb1:
- bb2:
- x = PHI (CONST, a)
-
- Gets replaced with:
- bb0:
- bb2:
- t1 = a == CONST;
- t2 = b > c;
- t3 = t1 & t2;
- x = a;
-
- ABS Replacement
- ---------------
-
- This transformation, implemented in match_simplify_replacement, replaces
-
- bb0:
- if (a >= 0) goto bb2; else goto bb1;
- bb1:
- x = -a;
- bb2:
- x = PHI <x (bb1), a (bb0), ...>;
-
- with
-
- bb0:
- x' = ABS_EXPR< a >;
- bb2:
- x = PHI <x' (bb0), ...>;
-
- MIN/MAX Replacement
- -------------------
-
- This transformation, minmax_replacement replaces
-
- bb0:
- if (a <= b) goto bb2; else goto bb1;
- bb1:
- bb2:
- x = PHI <b (bb1), a (bb0), ...>;
-
- with
-
- bb0:
- x' = MIN_EXPR (a, b)
- bb2:
- x = PHI <x' (bb0), ...>;
-
- A similar transformation is done for MAX_EXPR.
-
-
- This pass also performs a fifth transformation of a slightly different
- flavor.
-
- Factor conversion in COND_EXPR
- ------------------------------
-
- This transformation factors the conversion out of COND_EXPR with
- factor_out_conditional_conversion.
-
- For example:
- if (a <= CST) goto <bb 3>; else goto <bb 4>;
- <bb 3>:
- tmp = (int) a;
- <bb 4>:
- tmp = PHI <tmp, CST>
-
- Into:
- if (a <= CST) goto <bb 3>; else goto <bb 4>;
- <bb 3>:
- <bb 4>:
- a = PHI <a, CST>
- tmp = (int) a;
-
- Adjacent Load Hoisting
- ----------------------
-
- This transformation replaces
-
- bb0:
- if (...) goto bb2; else goto bb1;
- bb1:
- x1 = (<expr>).field1;
- goto bb3;
- bb2:
- x2 = (<expr>).field2;
- bb3:
- # x = PHI <x1, x2>;
-
- with
-
- bb0:
- x1 = (<expr>).field1;
- x2 = (<expr>).field2;
- if (...) goto bb2; else goto bb1;
- bb1:
- goto bb3;
- bb2:
- bb3:
- # x = PHI <x1, x2>;
-
- The purpose of this transformation is to enable generation of conditional
- move instructions such as Intel CMOVE or PowerPC ISEL. Because one of
- the loads is speculative, the transformation is restricted to very
- specific cases to avoid introducing a page fault. We are looking for
- the common idiom:
-
- if (...)
- x = y->left;
- else
- x = y->right;
-
- where left and right are typically adjacent pointers in a tree structure. */
-
-namespace {
-
-const pass_data pass_data_phiopt =
-{
- GIMPLE_PASS, /* type */
- "phiopt", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- TV_TREE_PHIOPT, /* tv_id */
- ( PROP_cfg | PROP_ssa ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_phiopt : public gimple_opt_pass
-{
-public:
- pass_phiopt (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_phiopt, ctxt), early_p (false)
- {}
-
- /* opt_pass methods: */
- opt_pass * clone () { return new pass_phiopt (m_ctxt); }
- void set_pass_param (unsigned n, bool param)
- {
- gcc_assert (n == 0);
- early_p = param;
- }
- virtual bool gate (function *) { return flag_ssa_phiopt; }
- virtual unsigned int execute (function *)
- {
- return tree_ssa_phiopt_worker (false,
- !early_p ? gate_hoist_loads () : false,
- early_p);
- }
-
-private:
- bool early_p;
-}; // class pass_phiopt
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_phiopt (gcc::context *ctxt)
-{
- return new pass_phiopt (ctxt);
-}
-
-namespace {
-
-const pass_data pass_data_cselim =
-{
- GIMPLE_PASS, /* type */
- "cselim", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- TV_TREE_PHIOPT, /* tv_id */
- ( PROP_cfg | PROP_ssa ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_cselim : public gimple_opt_pass
-{
-public:
- pass_cselim (gcc::context *ctxt)
- : gimple_opt_pass (pass_data_cselim, ctxt)
- {}
-
- /* opt_pass methods: */
- virtual bool gate (function *) { return flag_tree_cselim; }
- virtual unsigned int execute (function *) { return tree_ssa_cs_elim (); }
-
-}; // class pass_cselim
-
-} // anon namespace
-
-gimple_opt_pass *
-make_pass_cselim (gcc::context *ctxt)
-{
- return new pass_cselim (ctxt);
-}