diff options
author | Martin Liska <mliska@suse.cz> | 2022-01-14 16:56:44 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-01-17 22:12:04 +0100 |
commit | 5c69acb32329d49e58c26fa41ae74229a52b9106 (patch) | |
tree | ddb05f9d73afb6f998457d2ac4b720e3b3b60483 /gcc/tree-if-conv.c | |
parent | 490e23032baaece71f2ec09fa1805064b150fbc2 (diff) | |
download | gcc-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-if-conv.c')
-rw-r--r-- | gcc/tree-if-conv.c | 3510 |
1 files changed, 0 insertions, 3510 deletions
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c deleted file mode 100644 index 8baecea..0000000 --- a/gcc/tree-if-conv.c +++ /dev/null @@ -1,3510 +0,0 @@ -/* If-conversion for vectorizer. - Copyright (C) 2004-2022 Free Software Foundation, Inc. - Contributed by Devang Patel <dpatel@apple.com> - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -/* This pass implements a tree level if-conversion of loops. Its - initial goal is to help the vectorizer to vectorize loops with - conditions. - - A short description of if-conversion: - - o Decide if a loop is if-convertible or not. - o Walk all loop basic blocks in breadth first order (BFS order). - o Remove conditional statements (at the end of basic block) - and propagate condition into destination basic blocks' - predicate list. - o Replace modify expression with conditional modify expression - using current basic block's condition. - o Merge all basic blocks - o Replace phi nodes with conditional modify expr - o Merge all basic blocks into header - - Sample transformation: - - INPUT - ----- - - # i_23 = PHI <0(0), i_18(10)>; - <L0>:; - j_15 = A[i_23]; - if (j_15 > 41) goto <L1>; else goto <L17>; - - <L17>:; - goto <bb 3> (<L3>); - - <L1>:; - - # iftmp.2_4 = PHI <0(8), 42(2)>; - <L3>:; - A[i_23] = iftmp.2_4; - i_18 = i_23 + 1; - if (i_18 <= 15) goto <L19>; else goto <L18>; - - <L19>:; - goto <bb 1> (<L0>); - - <L18>:; - - OUTPUT - ------ - - # i_23 = PHI <0(0), i_18(10)>; - <L0>:; - j_15 = A[i_23]; - - <L3>:; - iftmp.2_4 = j_15 > 41 ? 42 : 0; - A[i_23] = iftmp.2_4; - i_18 = i_23 + 1; - if (i_18 <= 15) goto <L19>; else goto <L18>; - - <L19>:; - goto <bb 1> (<L0>); - - <L18>:; -*/ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "backend.h" -#include "rtl.h" -#include "tree.h" -#include "gimple.h" -#include "cfghooks.h" -#include "tree-pass.h" -#include "ssa.h" -#include "expmed.h" -#include "optabs-query.h" -#include "gimple-pretty-print.h" -#include "alias.h" -#include "fold-const.h" -#include "stor-layout.h" -#include "gimple-fold.h" -#include "gimplify.h" -#include "gimple-iterator.h" -#include "gimplify-me.h" -#include "tree-cfg.h" -#include "tree-into-ssa.h" -#include "tree-ssa.h" -#include "cfgloop.h" -#include "tree-data-ref.h" -#include "tree-scalar-evolution.h" -#include "tree-ssa-loop.h" -#include "tree-ssa-loop-niter.h" -#include "tree-ssa-loop-ivopts.h" -#include "tree-ssa-address.h" -#include "dbgcnt.h" -#include "tree-hash-traits.h" -#include "varasm.h" -#include "builtins.h" -#include "cfganal.h" -#include "internal-fn.h" -#include "fold-const.h" -#include "tree-ssa-sccvn.h" -#include "tree-cfgcleanup.h" -#include "tree-ssa-dse.h" -#include "tree-vectorizer.h" -#include "tree-eh.h" - -/* Only handle PHIs with no more arguments unless we are asked to by - simd pragma. */ -#define MAX_PHI_ARG_NUM \ - ((unsigned) param_max_tree_if_conversion_phi_args) - -/* True if we've converted a statement that was only executed when some - condition C was true, and if for correctness we need to predicate the - statement to ensure that it is a no-op when C is false. See - predicate_statements for the kinds of predication we support. */ -static bool need_to_predicate; - -/* True if we have to rewrite stmts that may invoke undefined behavior - when a condition C was false so it doesn't if it is always executed. - See predicate_statements for the kinds of predication we support. */ -static bool need_to_rewrite_undefined; - -/* Indicate if there are any complicated PHIs that need to be handled in - if-conversion. Complicated PHI has more than two arguments and can't - be degenerated to two arguments PHI. See more information in comment - before phi_convertible_by_degenerating_args. */ -static bool any_complicated_phi; - -/* Hash for struct innermost_loop_behavior. It depends on the user to - free the memory. */ - -struct innermost_loop_behavior_hash : nofree_ptr_hash <innermost_loop_behavior> -{ - static inline hashval_t hash (const value_type &); - static inline bool equal (const value_type &, - const compare_type &); -}; - -inline hashval_t -innermost_loop_behavior_hash::hash (const value_type &e) -{ - hashval_t hash; - - hash = iterative_hash_expr (e->base_address, 0); - hash = iterative_hash_expr (e->offset, hash); - hash = iterative_hash_expr (e->init, hash); - return iterative_hash_expr (e->step, hash); -} - -inline bool -innermost_loop_behavior_hash::equal (const value_type &e1, - const compare_type &e2) -{ - if ((e1->base_address && !e2->base_address) - || (!e1->base_address && e2->base_address) - || (!e1->offset && e2->offset) - || (e1->offset && !e2->offset) - || (!e1->init && e2->init) - || (e1->init && !e2->init) - || (!e1->step && e2->step) - || (e1->step && !e2->step)) - return false; - - if (e1->base_address && e2->base_address - && !operand_equal_p (e1->base_address, e2->base_address, 0)) - return false; - if (e1->offset && e2->offset - && !operand_equal_p (e1->offset, e2->offset, 0)) - return false; - if (e1->init && e2->init - && !operand_equal_p (e1->init, e2->init, 0)) - return false; - if (e1->step && e2->step - && !operand_equal_p (e1->step, e2->step, 0)) - return false; - - return true; -} - -/* List of basic blocks in if-conversion-suitable order. */ -static basic_block *ifc_bbs; - -/* Hash table to store <DR's innermost loop behavior, DR> pairs. */ -static hash_map<innermost_loop_behavior_hash, - data_reference_p> *innermost_DR_map; - -/* Hash table to store <base reference, DR> pairs. */ -static hash_map<tree_operand_hash, data_reference_p> *baseref_DR_map; - -/* List of redundant SSA names: the first should be replaced by the second. */ -static vec< std::pair<tree, tree> > redundant_ssa_names; - -/* Structure used to predicate basic blocks. This is attached to the - ->aux field of the BBs in the loop to be if-converted. */ -struct bb_predicate { - - /* The condition under which this basic block is executed. */ - tree predicate; - - /* PREDICATE is gimplified, and the sequence of statements is - recorded here, in order to avoid the duplication of computations - that occur in previous conditions. See PR44483. */ - gimple_seq predicate_gimplified_stmts; -}; - -/* Returns true when the basic block BB has a predicate. */ - -static inline bool -bb_has_predicate (basic_block bb) -{ - return bb->aux != NULL; -} - -/* Returns the gimplified predicate for basic block BB. */ - -static inline tree -bb_predicate (basic_block bb) -{ - return ((struct bb_predicate *) bb->aux)->predicate; -} - -/* Sets the gimplified predicate COND for basic block BB. */ - -static inline void -set_bb_predicate (basic_block bb, tree cond) -{ - gcc_assert ((TREE_CODE (cond) == TRUTH_NOT_EXPR - && is_gimple_condexpr (TREE_OPERAND (cond, 0))) - || is_gimple_condexpr (cond)); - ((struct bb_predicate *) bb->aux)->predicate = cond; -} - -/* Returns the sequence of statements of the gimplification of the - predicate for basic block BB. */ - -static inline gimple_seq -bb_predicate_gimplified_stmts (basic_block bb) -{ - return ((struct bb_predicate *) bb->aux)->predicate_gimplified_stmts; -} - -/* Sets the sequence of statements STMTS of the gimplification of the - predicate for basic block BB. */ - -static inline void -set_bb_predicate_gimplified_stmts (basic_block bb, gimple_seq stmts) -{ - ((struct bb_predicate *) bb->aux)->predicate_gimplified_stmts = stmts; -} - -/* Adds the sequence of statements STMTS to the sequence of statements - of the predicate for basic block BB. */ - -static inline void -add_bb_predicate_gimplified_stmts (basic_block bb, gimple_seq stmts) -{ - /* We might have updated some stmts in STMTS via force_gimple_operand - calling fold_stmt and that producing multiple stmts. Delink immediate - uses so update_ssa after loop versioning doesn't get confused for - the not yet inserted predicates. - ??? This should go away once we reliably avoid updating stmts - not in any BB. */ - for (gimple_stmt_iterator gsi = gsi_start (stmts); - !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple *stmt = gsi_stmt (gsi); - delink_stmt_imm_use (stmt); - gimple_set_modified (stmt, true); - } - gimple_seq_add_seq_without_update - (&(((struct bb_predicate *) bb->aux)->predicate_gimplified_stmts), stmts); -} - -/* Initializes to TRUE the predicate of basic block BB. */ - -static inline void -init_bb_predicate (basic_block bb) -{ - bb->aux = XNEW (struct bb_predicate); - set_bb_predicate_gimplified_stmts (bb, NULL); - set_bb_predicate (bb, boolean_true_node); -} - -/* Release the SSA_NAMEs associated with the predicate of basic block BB. */ - -static inline void -release_bb_predicate (basic_block bb) -{ - gimple_seq stmts = bb_predicate_gimplified_stmts (bb); - if (stmts) - { - /* Ensure that these stmts haven't yet been added to a bb. */ - if (flag_checking) - for (gimple_stmt_iterator i = gsi_start (stmts); - !gsi_end_p (i); gsi_next (&i)) - gcc_assert (! gimple_bb (gsi_stmt (i))); - - /* Discard them. */ - gimple_seq_discard (stmts); - set_bb_predicate_gimplified_stmts (bb, NULL); - } -} - -/* Free the predicate of basic block BB. */ - -static inline void -free_bb_predicate (basic_block bb) -{ - if (!bb_has_predicate (bb)) - return; - - release_bb_predicate (bb); - free (bb->aux); - bb->aux = NULL; -} - -/* Reinitialize predicate of BB with the true predicate. */ - -static inline void -reset_bb_predicate (basic_block bb) -{ - if (!bb_has_predicate (bb)) - init_bb_predicate (bb); - else - { - release_bb_predicate (bb); - set_bb_predicate (bb, boolean_true_node); - } -} - -/* Returns a new SSA_NAME of type TYPE that is assigned the value of - the expression EXPR. Inserts the statement created for this - computation before GSI and leaves the iterator GSI at the same - statement. */ - -static tree -ifc_temp_var (tree type, tree expr, gimple_stmt_iterator *gsi) -{ - tree new_name = make_temp_ssa_name (type, NULL, "_ifc_"); - gimple *stmt = gimple_build_assign (new_name, expr); - gimple_set_vuse (stmt, gimple_vuse (gsi_stmt (*gsi))); - gsi_insert_before (gsi, stmt, GSI_SAME_STMT); - return new_name; -} - -/* Return true when COND is a false predicate. */ - -static inline bool -is_false_predicate (tree cond) -{ - return (cond != NULL_TREE - && (cond == boolean_false_node - || integer_zerop (cond))); -} - -/* Return true when COND is a true predicate. */ - -static inline bool -is_true_predicate (tree cond) -{ - return (cond == NULL_TREE - || cond == boolean_true_node - || integer_onep (cond)); -} - -/* Returns true when BB has a predicate that is not trivial: true or - NULL_TREE. */ - -static inline bool -is_predicated (basic_block bb) -{ - return !is_true_predicate (bb_predicate (bb)); -} - -/* Parses the predicate COND and returns its comparison code and - operands OP0 and OP1. */ - -static enum tree_code -parse_predicate (tree cond, tree *op0, tree *op1) -{ - gimple *s; - - if (TREE_CODE (cond) == SSA_NAME - && is_gimple_assign (s = SSA_NAME_DEF_STMT (cond))) - { - if (TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison) - { - *op0 = gimple_assign_rhs1 (s); - *op1 = gimple_assign_rhs2 (s); - return gimple_assign_rhs_code (s); - } - - else if (gimple_assign_rhs_code (s) == TRUTH_NOT_EXPR) - { - tree op = gimple_assign_rhs1 (s); - tree type = TREE_TYPE (op); - enum tree_code code = parse_predicate (op, op0, op1); - - return code == ERROR_MARK ? ERROR_MARK - : invert_tree_comparison (code, HONOR_NANS (type)); - } - - return ERROR_MARK; - } - - if (COMPARISON_CLASS_P (cond)) - { - *op0 = TREE_OPERAND (cond, 0); - *op1 = TREE_OPERAND (cond, 1); - return TREE_CODE (cond); - } - - return ERROR_MARK; -} - -/* Returns the fold of predicate C1 OR C2 at location LOC. */ - -static tree -fold_or_predicates (location_t loc, tree c1, tree c2) -{ - tree op1a, op1b, op2a, op2b; - enum tree_code code1 = parse_predicate (c1, &op1a, &op1b); - enum tree_code code2 = parse_predicate (c2, &op2a, &op2b); - - if (code1 != ERROR_MARK && code2 != ERROR_MARK) - { - tree t = maybe_fold_or_comparisons (boolean_type_node, code1, op1a, op1b, - code2, op2a, op2b); - if (t) - return t; - } - - return fold_build2_loc (loc, TRUTH_OR_EXPR, boolean_type_node, c1, c2); -} - -/* Returns either a COND_EXPR or the folded expression if the folded - expression is a MIN_EXPR, a MAX_EXPR, an ABS_EXPR, - a constant or a SSA_NAME. */ - -static tree -fold_build_cond_expr (tree type, tree cond, tree rhs, tree lhs) -{ - tree rhs1, lhs1, cond_expr; - - /* If COND is comparison r != 0 and r has boolean type, convert COND - to SSA_NAME to accept by vect bool pattern. */ - if (TREE_CODE (cond) == NE_EXPR) - { - tree op0 = TREE_OPERAND (cond, 0); - tree op1 = TREE_OPERAND (cond, 1); - if (TREE_CODE (op0) == SSA_NAME - && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE - && (integer_zerop (op1))) - cond = op0; - } - cond_expr = fold_ternary (COND_EXPR, type, cond, rhs, lhs); - - if (cond_expr == NULL_TREE) - return build3 (COND_EXPR, type, cond, rhs, lhs); - - STRIP_USELESS_TYPE_CONVERSION (cond_expr); - - if (is_gimple_val (cond_expr)) - return cond_expr; - - if (TREE_CODE (cond_expr) == ABS_EXPR) - { - rhs1 = TREE_OPERAND (cond_expr, 1); - STRIP_USELESS_TYPE_CONVERSION (rhs1); - if (is_gimple_val (rhs1)) - return build1 (ABS_EXPR, type, rhs1); - } - - if (TREE_CODE (cond_expr) == MIN_EXPR - || TREE_CODE (cond_expr) == MAX_EXPR) - { - lhs1 = TREE_OPERAND (cond_expr, 0); - STRIP_USELESS_TYPE_CONVERSION (lhs1); - rhs1 = TREE_OPERAND (cond_expr, 1); - STRIP_USELESS_TYPE_CONVERSION (rhs1); - if (is_gimple_val (rhs1) && is_gimple_val (lhs1)) - return build2 (TREE_CODE (cond_expr), type, lhs1, rhs1); - } - return build3 (COND_EXPR, type, cond, rhs, lhs); -} - -/* Add condition NC to the predicate list of basic block BB. LOOP is - the loop to be if-converted. Use predicate of cd-equivalent block - for join bb if it exists: we call basic blocks bb1 and bb2 - cd-equivalent if they are executed under the same condition. */ - -static inline void -add_to_predicate_list (class loop *loop, basic_block bb, tree nc) -{ - tree bc, *tp; - basic_block dom_bb; - - if (is_true_predicate (nc)) - return; - - /* If dominance tells us this basic block is always executed, - don't record any predicates for it. */ - if (dominated_by_p (CDI_DOMINATORS, loop->latch, bb)) - return; - - dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb); - /* We use notion of cd equivalence to get simpler predicate for - join block, e.g. if join block has 2 predecessors with predicates - p1 & p2 and p1 & !p2, we'd like to get p1 for it instead of - p1 & p2 | p1 & !p2. */ - if (dom_bb != loop->header - && get_immediate_dominator (CDI_POST_DOMINATORS, dom_bb) == bb) - { - gcc_assert (flow_bb_inside_loop_p (loop, dom_bb)); - bc = bb_predicate (dom_bb); - if (!is_true_predicate (bc)) - set_bb_predicate (bb, bc); - else - gcc_assert (is_true_predicate (bb_predicate (bb))); - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Use predicate of bb#%d for bb#%d\n", - dom_bb->index, bb->index); - return; - } - - if (!is_predicated (bb)) - bc = nc; - else - { - bc = bb_predicate (bb); - bc = fold_or_predicates (EXPR_LOCATION (bc), nc, bc); - if (is_true_predicate (bc)) - { - reset_bb_predicate (bb); - return; - } - } - - /* Allow a TRUTH_NOT_EXPR around the main predicate. */ - if (TREE_CODE (bc) == TRUTH_NOT_EXPR) - tp = &TREE_OPERAND (bc, 0); - else - tp = &bc; - if (!is_gimple_condexpr (*tp)) - { - gimple_seq stmts; - *tp = force_gimple_operand_1 (*tp, &stmts, is_gimple_condexpr, NULL_TREE); - add_bb_predicate_gimplified_stmts (bb, stmts); - } - set_bb_predicate (bb, bc); -} - -/* Add the condition COND to the previous condition PREV_COND, and add - this to the predicate list of the destination of edge E. LOOP is - the loop to be if-converted. */ - -static void -add_to_dst_predicate_list (class loop *loop, edge e, - tree prev_cond, tree cond) -{ - if (!flow_bb_inside_loop_p (loop, e->dest)) - return; - - if (!is_true_predicate (prev_cond)) - cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, - prev_cond, cond); - - if (!dominated_by_p (CDI_DOMINATORS, loop->latch, e->dest)) - add_to_predicate_list (loop, e->dest, cond); -} - -/* Return true if one of the successor edges of BB exits LOOP. */ - -static bool -bb_with_exit_edge_p (class loop *loop, basic_block bb) -{ - edge e; - edge_iterator ei; - - FOR_EACH_EDGE (e, ei, bb->succs) - if (loop_exit_edge_p (loop, e)) - return true; - - return false; -} - -/* Given PHI which has more than two arguments, this function checks if - it's if-convertible by degenerating its arguments. Specifically, if - below two conditions are satisfied: - - 1) Number of PHI arguments with different values equals to 2 and one - argument has the only occurrence. - 2) The edge corresponding to the unique argument isn't critical edge. - - Such PHI can be handled as PHIs have only two arguments. For example, - below PHI: - - res = PHI <A_1(e1), A_1(e2), A_2(e3)>; - - can be transformed into: - - res = (predicate of e3) ? A_2 : A_1; - - Return TRUE if it is the case, FALSE otherwise. */ - -static bool -phi_convertible_by_degenerating_args (gphi *phi) -{ - edge e; - tree arg, t1 = NULL, t2 = NULL; - unsigned int i, i1 = 0, i2 = 0, n1 = 0, n2 = 0; - unsigned int num_args = gimple_phi_num_args (phi); - - gcc_assert (num_args > 2); - - for (i = 0; i < num_args; i++) - { - arg = gimple_phi_arg_def (phi, i); - if (t1 == NULL || operand_equal_p (t1, arg, 0)) - { - n1++; - i1 = i; - t1 = arg; - } - else if (t2 == NULL || operand_equal_p (t2, arg, 0)) - { - n2++; - i2 = i; - t2 = arg; - } - else - return false; - } - - if (n1 != 1 && n2 != 1) - return false; - - /* Check if the edge corresponding to the unique arg is critical. */ - e = gimple_phi_arg_edge (phi, (n1 == 1) ? i1 : i2); - if (EDGE_COUNT (e->src->succs) > 1) - return false; - - return true; -} - -/* Return true when PHI is if-convertible. PHI is part of loop LOOP - and it belongs to basic block BB. Note at this point, it is sure - that PHI is if-convertible. This function updates global variable - ANY_COMPLICATED_PHI if PHI is complicated. */ - -static bool -if_convertible_phi_p (class loop *loop, basic_block bb, gphi *phi) -{ - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "-------------------------\n"); - print_gimple_stmt (dump_file, phi, 0, TDF_SLIM); - } - - if (bb != loop->header - && gimple_phi_num_args (phi) > 2 - && !phi_convertible_by_degenerating_args (phi)) - any_complicated_phi = true; - - return true; -} - -/* Records the status of a data reference. This struct is attached to - each DR->aux field. */ - -struct ifc_dr { - bool rw_unconditionally; - bool w_unconditionally; - bool written_at_least_once; - - tree rw_predicate; - tree w_predicate; - tree base_w_predicate; -}; - -#define IFC_DR(DR) ((struct ifc_dr *) (DR)->aux) -#define DR_BASE_W_UNCONDITIONALLY(DR) (IFC_DR (DR)->written_at_least_once) -#define DR_RW_UNCONDITIONALLY(DR) (IFC_DR (DR)->rw_unconditionally) -#define DR_W_UNCONDITIONALLY(DR) (IFC_DR (DR)->w_unconditionally) - -/* Iterates over DR's and stores refs, DR and base refs, DR pairs in - HASH tables. While storing them in HASH table, it checks if the - reference is unconditionally read or written and stores that as a flag - information. For base reference it checks if it is written atlest once - unconditionally and stores it as flag information along with DR. - In other words for every data reference A in STMT there exist other - accesses to a data reference with the same base with predicates that - add up (OR-up) to the true predicate: this ensures that the data - reference A is touched (read or written) on every iteration of the - if-converted loop. */ -static void -hash_memrefs_baserefs_and_store_DRs_read_written_info (data_reference_p a) -{ - - data_reference_p *master_dr, *base_master_dr; - tree base_ref = DR_BASE_OBJECT (a); - innermost_loop_behavior *innermost = &DR_INNERMOST (a); - tree ca = bb_predicate (gimple_bb (DR_STMT (a))); - bool exist1, exist2; - - master_dr = &innermost_DR_map->get_or_insert (innermost, &exist1); - if (!exist1) - *master_dr = a; - - if (DR_IS_WRITE (a)) - { - IFC_DR (*master_dr)->w_predicate - = fold_or_predicates (UNKNOWN_LOCATION, ca, - IFC_DR (*master_dr)->w_predicate); - if (is_true_predicate (IFC_DR (*master_dr)->w_predicate)) - DR_W_UNCONDITIONALLY (*master_dr) = true; - } - IFC_DR (*master_dr)->rw_predicate - = fold_or_predicates (UNKNOWN_LOCATION, ca, - IFC_DR (*master_dr)->rw_predicate); - if (is_true_predicate (IFC_DR (*master_dr)->rw_predicate)) - DR_RW_UNCONDITIONALLY (*master_dr) = true; - - if (DR_IS_WRITE (a)) - { - base_master_dr = &baseref_DR_map->get_or_insert (base_ref, &exist2); - if (!exist2) - *base_master_dr = a; - IFC_DR (*base_master_dr)->base_w_predicate - = fold_or_predicates (UNKNOWN_LOCATION, ca, - IFC_DR (*base_master_dr)->base_w_predicate); - if (is_true_predicate (IFC_DR (*base_master_dr)->base_w_predicate)) - DR_BASE_W_UNCONDITIONALLY (*base_master_dr) = true; - } -} - -/* Return TRUE if can prove the index IDX of an array reference REF is - within array bound. Return false otherwise. */ - -static bool -idx_within_array_bound (tree ref, tree *idx, void *dta) -{ - wi::overflow_type overflow; - widest_int niter, valid_niter, delta, wi_step; - tree ev, init, step; - tree low, high; - class loop *loop = (class loop*) dta; - - /* Only support within-bound access for array references. */ - if (TREE_CODE (ref) != ARRAY_REF) - return false; - - /* For arrays at the end of the structure, we are not guaranteed that they - do not really extend over their declared size. However, for arrays of - size greater than one, this is unlikely to be intended. */ - if (array_at_struct_end_p (ref)) - return false; - - ev = analyze_scalar_evolution (loop, *idx); - ev = instantiate_parameters (loop, ev); - init = initial_condition (ev); - step = evolution_part_in_loop_num (ev, loop->num); - - if (!init || TREE_CODE (init) != INTEGER_CST - || (step && TREE_CODE (step) != INTEGER_CST)) - return false; - - low = array_ref_low_bound (ref); - high = array_ref_up_bound (ref); - - /* The case of nonconstant bounds could be handled, but it would be - complicated. */ - if (TREE_CODE (low) != INTEGER_CST - || !high || TREE_CODE (high) != INTEGER_CST) - return false; - - /* Check if the intial idx is within bound. */ - if (wi::to_widest (init) < wi::to_widest (low) - || wi::to_widest (init) > wi::to_widest (high)) - return false; - - /* The idx is always within bound. */ - if (!step || integer_zerop (step)) - return true; - - if (!max_loop_iterations (loop, &niter)) - return false; - - if (wi::to_widest (step) < 0) - { - delta = wi::to_widest (init) - wi::to_widest (low); - wi_step = -wi::to_widest (step); - } - else - { - delta = wi::to_widest (high) - wi::to_widest (init); - wi_step = wi::to_widest (step); - } - - valid_niter = wi::div_floor (delta, wi_step, SIGNED, &overflow); - /* The iteration space of idx is within array bound. */ - if (!overflow && niter <= valid_niter) - return true; - - return false; -} - -/* Return TRUE if ref is a within bound array reference. */ - -static bool -ref_within_array_bound (gimple *stmt, tree ref) -{ - class loop *loop = loop_containing_stmt (stmt); - - gcc_assert (loop != NULL); - return for_each_index (&ref, idx_within_array_bound, loop); -} - - -/* Given a memory reference expression T, return TRUE if base object - it refers to is writable. The base object of a memory reference - is the main object being referenced, which is returned by function - get_base_address. */ - -static bool -base_object_writable (tree ref) -{ - tree base_tree = get_base_address (ref); - - return (base_tree - && DECL_P (base_tree) - && decl_binds_to_current_def_p (base_tree) - && !TREE_READONLY (base_tree)); -} - -/* Return true when the memory references of STMT won't trap in the - if-converted code. There are two things that we have to check for: - - - writes to memory occur to writable memory: if-conversion of - memory writes transforms the conditional memory writes into - unconditional writes, i.e. "if (cond) A[i] = foo" is transformed - into "A[i] = cond ? foo : A[i]", and as the write to memory may not - be executed at all in the original code, it may be a readonly - memory. To check that A is not const-qualified, we check that - there exists at least an unconditional write to A in the current - function. - - - reads or writes to memory are valid memory accesses for every - iteration. To check that the memory accesses are correctly formed - and that we are allowed to read and write in these locations, we - check that the memory accesses to be if-converted occur at every - iteration unconditionally. - - Returns true for the memory reference in STMT, same memory reference - is read or written unconditionally atleast once and the base memory - reference is written unconditionally once. This is to check reference - will not write fault. Also retuns true if the memory reference is - unconditionally read once then we are conditionally writing to memory - which is defined as read and write and is bound to the definition - we are seeing. */ -static bool -ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> drs) -{ - /* If DR didn't see a reference here we can't use it to tell - whether the ref traps or not. */ - if (gimple_uid (stmt) == 0) - return false; - - data_reference_p *master_dr, *base_master_dr; - data_reference_p a = drs[gimple_uid (stmt) - 1]; - - tree base = DR_BASE_OBJECT (a); - innermost_loop_behavior *innermost = &DR_INNERMOST (a); - - gcc_assert (DR_STMT (a) == stmt); - gcc_assert (DR_BASE_ADDRESS (a) || DR_OFFSET (a) - || DR_INIT (a) || DR_STEP (a)); - - master_dr = innermost_DR_map->get (innermost); - gcc_assert (master_dr != NULL); - - base_master_dr = baseref_DR_map->get (base); - - /* If a is unconditionally written to it doesn't trap. */ - if (DR_W_UNCONDITIONALLY (*master_dr)) - return true; - - /* If a is unconditionally accessed then ... - - Even a is conditional access, we can treat it as an unconditional - one if it's an array reference and all its index are within array - bound. */ - if (DR_RW_UNCONDITIONALLY (*master_dr) - || ref_within_array_bound (stmt, DR_REF (a))) - { - /* an unconditional read won't trap. */ - if (DR_IS_READ (a)) - return true; - - /* an unconditionaly write won't trap if the base is written - to unconditionally. */ - if (base_master_dr - && DR_BASE_W_UNCONDITIONALLY (*base_master_dr)) - return flag_store_data_races; - /* or the base is known to be not readonly. */ - else if (base_object_writable (DR_REF (a))) - return flag_store_data_races; - } - - return false; -} - -/* Return true if STMT could be converted into a masked load or store - (conditional load or store based on a mask computed from bb predicate). */ - -static bool -ifcvt_can_use_mask_load_store (gimple *stmt) -{ - /* Check whether this is a load or store. */ - tree lhs = gimple_assign_lhs (stmt); - bool is_load; - tree ref; - if (gimple_store_p (stmt)) - { - if (!is_gimple_val (gimple_assign_rhs1 (stmt))) - return false; - is_load = false; - ref = lhs; - } - else if (gimple_assign_load_p (stmt)) - { - is_load = true; - ref = gimple_assign_rhs1 (stmt); - } - else - return false; - - if (may_be_nonaddressable_p (ref)) - return false; - - /* Mask should be integer mode of the same size as the load/store - mode. */ - machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); - if (!int_mode_for_mode (mode).exists () || VECTOR_MODE_P (mode)) - return false; - - if (can_vec_mask_load_store_p (mode, VOIDmode, is_load)) - return true; - - return false; -} - -/* Return true if STMT could be converted from an operation that is - unconditional to one that is conditional on a bb predicate mask. */ - -static bool -ifcvt_can_predicate (gimple *stmt) -{ - basic_block bb = gimple_bb (stmt); - - if (!(flag_tree_loop_vectorize || bb->loop_father->force_vectorize) - || bb->loop_father->dont_vectorize - || gimple_has_volatile_ops (stmt)) - return false; - - if (gimple_assign_single_p (stmt)) - return ifcvt_can_use_mask_load_store (stmt); - - tree_code code = gimple_assign_rhs_code (stmt); - tree lhs_type = TREE_TYPE (gimple_assign_lhs (stmt)); - tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (stmt)); - if (!types_compatible_p (lhs_type, rhs_type)) - return false; - internal_fn cond_fn = get_conditional_internal_fn (code); - return (cond_fn != IFN_LAST - && vectorized_internal_fn_supported_p (cond_fn, lhs_type)); -} - -/* Return true when STMT is if-convertible. - - GIMPLE_ASSIGN statement is not if-convertible if, - - it is not movable, - - it could trap, - - LHS is not var decl. */ - -static bool -if_convertible_gimple_assign_stmt_p (gimple *stmt, - vec<data_reference_p> refs) -{ - tree lhs = gimple_assign_lhs (stmt); - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "-------------------------\n"); - print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); - } - - if (!is_gimple_reg_type (TREE_TYPE (lhs))) - return false; - - /* Some of these constrains might be too conservative. */ - if (stmt_ends_bb_p (stmt) - || gimple_has_volatile_ops (stmt) - || (TREE_CODE (lhs) == SSA_NAME - && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) - || gimple_has_side_effects (stmt)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "stmt not suitable for ifcvt\n"); - return false; - } - - /* tree-into-ssa.c uses GF_PLF_1, so avoid it, because - in between if_convertible_loop_p and combine_blocks - we can perform loop versioning. */ - gimple_set_plf (stmt, GF_PLF_2, false); - - if ((! gimple_vuse (stmt) - || gimple_could_trap_p_1 (stmt, false, false) - || ! ifcvt_memrefs_wont_trap (stmt, refs)) - && gimple_could_trap_p (stmt)) - { - if (ifcvt_can_predicate (stmt)) - { - gimple_set_plf (stmt, GF_PLF_2, true); - need_to_predicate = true; - return true; - } - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "tree could trap...\n"); - return false; - } - else if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs)) - || POINTER_TYPE_P (TREE_TYPE (lhs))) - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs)) - && arith_code_with_undefined_signed_overflow - (gimple_assign_rhs_code (stmt))) - /* We have to rewrite stmts with undefined overflow. */ - need_to_rewrite_undefined = true; - - /* When if-converting stores force versioning, likewise if we - ended up generating store data races. */ - if (gimple_vdef (stmt)) - need_to_predicate = true; - - return true; -} - -/* Return true when STMT is if-convertible. - - A statement is if-convertible if: - - it is an if-convertible GIMPLE_ASSIGN, - - it is a GIMPLE_LABEL or a GIMPLE_COND, - - it is builtins call. */ - -static bool -if_convertible_stmt_p (gimple *stmt, vec<data_reference_p> refs) -{ - switch (gimple_code (stmt)) - { - case GIMPLE_LABEL: - case GIMPLE_DEBUG: - case GIMPLE_COND: - return true; - - case GIMPLE_ASSIGN: - return if_convertible_gimple_assign_stmt_p (stmt, refs); - - case GIMPLE_CALL: - { - tree fndecl = gimple_call_fndecl (stmt); - if (fndecl) - { - int flags = gimple_call_flags (stmt); - if ((flags & ECF_CONST) - && !(flags & ECF_LOOPING_CONST_OR_PURE) - /* We can only vectorize some builtins at the moment, - so restrict if-conversion to those. */ - && fndecl_built_in_p (fndecl)) - return true; - } - return false; - } - - default: - /* Don't know what to do with 'em so don't do anything. */ - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "don't know what to do\n"); - print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); - } - return false; - } -} - -/* Assumes that BB has more than 1 predecessors. - Returns false if at least one successor is not on critical edge - and true otherwise. */ - -static inline bool -all_preds_critical_p (basic_block bb) -{ - edge e; - edge_iterator ei; - - FOR_EACH_EDGE (e, ei, bb->preds) - if (EDGE_COUNT (e->src->succs) == 1) - return false; - return true; -} - -/* Return true when BB is if-convertible. This routine does not check - basic block's statements and phis. - - A basic block is not if-convertible if: - - it is non-empty and it is after the exit block (in BFS order), - - it is after the exit block but before the latch, - - its edges are not normal. - - EXIT_BB is the basic block containing the exit of the LOOP. BB is - inside LOOP. */ - -static bool -if_convertible_bb_p (class loop *loop, basic_block bb, basic_block exit_bb) -{ - edge e; - edge_iterator ei; - - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "----------[%d]-------------\n", bb->index); - - if (EDGE_COUNT (bb->succs) > 2) - return false; - - gimple *last = last_stmt (bb); - if (gcall *call = safe_dyn_cast <gcall *> (last)) - if (gimple_call_ctrl_altering_p (call)) - return false; - - if (exit_bb) - { - if (bb != loop->latch) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "basic block after exit bb but before latch\n"); - return false; - } - else if (!empty_block_p (bb)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "non empty basic block after exit bb\n"); - return false; - } - else if (bb == loop->latch - && bb != exit_bb - && !dominated_by_p (CDI_DOMINATORS, bb, exit_bb)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "latch is not dominated by exit_block\n"); - return false; - } - } - - /* Be less adventurous and handle only normal edges. */ - FOR_EACH_EDGE (e, ei, bb->succs) - if (e->flags & (EDGE_EH | EDGE_ABNORMAL | EDGE_IRREDUCIBLE_LOOP)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Difficult to handle edges\n"); - return false; - } - - return true; -} - -/* Return true when all predecessor blocks of BB are visited. The - VISITED bitmap keeps track of the visited blocks. */ - -static bool -pred_blocks_visited_p (basic_block bb, bitmap *visited) -{ - edge e; - edge_iterator ei; - FOR_EACH_EDGE (e, ei, bb->preds) - if (!bitmap_bit_p (*visited, e->src->index)) - return false; - - return true; -} - -/* Get body of a LOOP in suitable order for if-conversion. It is - caller's responsibility to deallocate basic block list. - If-conversion suitable order is, breadth first sort (BFS) order - with an additional constraint: select a block only if all its - predecessors are already selected. */ - -static basic_block * -get_loop_body_in_if_conv_order (const class loop *loop) -{ - basic_block *blocks, *blocks_in_bfs_order; - basic_block bb; - bitmap visited; - unsigned int index = 0; - unsigned int visited_count = 0; - - gcc_assert (loop->num_nodes); - gcc_assert (loop->latch != EXIT_BLOCK_PTR_FOR_FN (cfun)); - - blocks = XCNEWVEC (basic_block, loop->num_nodes); - visited = BITMAP_ALLOC (NULL); - - blocks_in_bfs_order = get_loop_body_in_bfs_order (loop); - - index = 0; - while (index < loop->num_nodes) - { - bb = blocks_in_bfs_order [index]; - - if (bb->flags & BB_IRREDUCIBLE_LOOP) - { - free (blocks_in_bfs_order); - BITMAP_FREE (visited); - free (blocks); - return NULL; - } - - if (!bitmap_bit_p (visited, bb->index)) - { - if (pred_blocks_visited_p (bb, &visited) - || bb == loop->header) - { - /* This block is now visited. */ - bitmap_set_bit (visited, bb->index); - blocks[visited_count++] = bb; - } - } - - index++; - - if (index == loop->num_nodes - && visited_count != loop->num_nodes) - /* Not done yet. */ - index = 0; - } - free (blocks_in_bfs_order); - BITMAP_FREE (visited); - return blocks; -} - -/* Returns true when the analysis of the predicates for all the basic - blocks in LOOP succeeded. - - predicate_bbs first allocates the predicates of the basic blocks. - These fields are then initialized with the tree expressions - representing the predicates under which a basic block is executed - in the LOOP. As the loop->header is executed at each iteration, it - has the "true" predicate. Other statements executed under a - condition are predicated with that condition, for example - - | if (x) - | S1; - | else - | S2; - - S1 will be predicated with "x", and - S2 will be predicated with "!x". */ - -static void -predicate_bbs (loop_p loop) -{ - unsigned int i; - - for (i = 0; i < loop->num_nodes; i++) - init_bb_predicate (ifc_bbs[i]); - - for (i = 0; i < loop->num_nodes; i++) - { - basic_block bb = ifc_bbs[i]; - tree cond; - gimple *stmt; - - /* The loop latch and loop exit block are always executed and - have no extra conditions to be processed: skip them. */ - if (bb == loop->latch - || bb_with_exit_edge_p (loop, bb)) - { - reset_bb_predicate (bb); - continue; - } - - cond = bb_predicate (bb); - stmt = last_stmt (bb); - if (stmt && gimple_code (stmt) == GIMPLE_COND) - { - tree c2; - edge true_edge, false_edge; - location_t loc = gimple_location (stmt); - tree c = build2_loc (loc, gimple_cond_code (stmt), - boolean_type_node, - gimple_cond_lhs (stmt), - gimple_cond_rhs (stmt)); - - /* Add new condition into destination's predicate list. */ - extract_true_false_edges_from_block (gimple_bb (stmt), - &true_edge, &false_edge); - - /* If C is true, then TRUE_EDGE is taken. */ - add_to_dst_predicate_list (loop, true_edge, unshare_expr (cond), - unshare_expr (c)); - - /* If C is false, then FALSE_EDGE is taken. */ - c2 = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, - unshare_expr (c)); - add_to_dst_predicate_list (loop, false_edge, - unshare_expr (cond), c2); - - cond = NULL_TREE; - } - - /* If current bb has only one successor, then consider it as an - unconditional goto. */ - if (single_succ_p (bb)) - { - basic_block bb_n = single_succ (bb); - - /* The successor bb inherits the predicate of its - predecessor. If there is no predicate in the predecessor - bb, then consider the successor bb as always executed. */ - if (cond == NULL_TREE) - cond = boolean_true_node; - - add_to_predicate_list (loop, bb_n, cond); - } - } - - /* The loop header is always executed. */ - reset_bb_predicate (loop->header); - gcc_assert (bb_predicate_gimplified_stmts (loop->header) == NULL - && bb_predicate_gimplified_stmts (loop->latch) == NULL); -} - -/* Build region by adding loop pre-header and post-header blocks. */ - -static vec<basic_block> -build_region (class loop *loop) -{ - vec<basic_block> region = vNULL; - basic_block exit_bb = NULL; - - gcc_assert (ifc_bbs); - /* The first element is loop pre-header. */ - region.safe_push (loop_preheader_edge (loop)->src); - - for (unsigned int i = 0; i < loop->num_nodes; i++) - { - basic_block bb = ifc_bbs[i]; - region.safe_push (bb); - /* Find loop postheader. */ - edge e; - edge_iterator ei; - FOR_EACH_EDGE (e, ei, bb->succs) - if (loop_exit_edge_p (loop, e)) - { - exit_bb = e->dest; - break; - } - } - /* The last element is loop post-header. */ - gcc_assert (exit_bb); - region.safe_push (exit_bb); - return region; -} - -/* Return true when LOOP is if-convertible. This is a helper function - for if_convertible_loop_p. REFS and DDRS are initialized and freed - in if_convertible_loop_p. */ - -static bool -if_convertible_loop_p_1 (class loop *loop, vec<data_reference_p> *refs) -{ - unsigned int i; - basic_block exit_bb = NULL; - vec<basic_block> region; - - if (find_data_references_in_loop (loop, refs) == chrec_dont_know) - return false; - - calculate_dominance_info (CDI_DOMINATORS); - - /* Allow statements that can be handled during if-conversion. */ - ifc_bbs = get_loop_body_in_if_conv_order (loop); - if (!ifc_bbs) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Irreducible loop\n"); - return false; - } - - for (i = 0; i < loop->num_nodes; i++) - { - basic_block bb = ifc_bbs[i]; - - if (!if_convertible_bb_p (loop, bb, exit_bb)) - return false; - - if (bb_with_exit_edge_p (loop, bb)) - exit_bb = bb; - } - - for (i = 0; i < loop->num_nodes; i++) - { - basic_block bb = ifc_bbs[i]; - gimple_stmt_iterator gsi; - - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - switch (gimple_code (gsi_stmt (gsi))) - { - case GIMPLE_LABEL: - case GIMPLE_ASSIGN: - case GIMPLE_CALL: - case GIMPLE_DEBUG: - case GIMPLE_COND: - gimple_set_uid (gsi_stmt (gsi), 0); - break; - default: - return false; - } - } - - data_reference_p dr; - - innermost_DR_map - = new hash_map<innermost_loop_behavior_hash, data_reference_p>; - baseref_DR_map = new hash_map<tree_operand_hash, data_reference_p>; - - /* Compute post-dominator tree locally. */ - region = build_region (loop); - calculate_dominance_info_for_region (CDI_POST_DOMINATORS, region); - - predicate_bbs (loop); - - /* Free post-dominator tree since it is not used after predication. */ - free_dominance_info_for_region (cfun, CDI_POST_DOMINATORS, region); - region.release (); - - for (i = 0; refs->iterate (i, &dr); i++) - { - tree ref = DR_REF (dr); - - dr->aux = XNEW (struct ifc_dr); - DR_BASE_W_UNCONDITIONALLY (dr) = false; - DR_RW_UNCONDITIONALLY (dr) = false; - DR_W_UNCONDITIONALLY (dr) = false; - IFC_DR (dr)->rw_predicate = boolean_false_node; - IFC_DR (dr)->w_predicate = boolean_false_node; - IFC_DR (dr)->base_w_predicate = boolean_false_node; - if (gimple_uid (DR_STMT (dr)) == 0) - gimple_set_uid (DR_STMT (dr), i + 1); - - /* If DR doesn't have innermost loop behavior or it's a compound - memory reference, we synthesize its innermost loop behavior - for hashing. */ - if (TREE_CODE (ref) == COMPONENT_REF - || TREE_CODE (ref) == IMAGPART_EXPR - || TREE_CODE (ref) == REALPART_EXPR - || !(DR_BASE_ADDRESS (dr) || DR_OFFSET (dr) - || DR_INIT (dr) || DR_STEP (dr))) - { - while (TREE_CODE (ref) == COMPONENT_REF - || TREE_CODE (ref) == IMAGPART_EXPR - || TREE_CODE (ref) == REALPART_EXPR) - ref = TREE_OPERAND (ref, 0); - - memset (&DR_INNERMOST (dr), 0, sizeof (DR_INNERMOST (dr))); - DR_BASE_ADDRESS (dr) = ref; - } - hash_memrefs_baserefs_and_store_DRs_read_written_info (dr); - } - - for (i = 0; i < loop->num_nodes; i++) - { - basic_block bb = ifc_bbs[i]; - gimple_stmt_iterator itr; - - /* Check the if-convertibility of statements in predicated BBs. */ - if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb)) - for (itr = gsi_start_bb (bb); !gsi_end_p (itr); gsi_next (&itr)) - if (!if_convertible_stmt_p (gsi_stmt (itr), *refs)) - return false; - } - - /* Checking PHIs needs to be done after stmts, as the fact whether there - are any masked loads or stores affects the tests. */ - for (i = 0; i < loop->num_nodes; i++) - { - basic_block bb = ifc_bbs[i]; - gphi_iterator itr; - - for (itr = gsi_start_phis (bb); !gsi_end_p (itr); gsi_next (&itr)) - if (!if_convertible_phi_p (loop, bb, itr.phi ())) - return false; - } - - if (dump_file) - fprintf (dump_file, "Applying if-conversion\n"); - - return true; -} - -/* Return true when LOOP is if-convertible. - LOOP is if-convertible if: - - it is innermost, - - it has two or more basic blocks, - - it has only one exit, - - loop header is not the exit edge, - - if its basic blocks and phi nodes are if convertible. */ - -static bool -if_convertible_loop_p (class loop *loop) -{ - edge e; - edge_iterator ei; - bool res = false; - vec<data_reference_p> refs; - - /* Handle only innermost loop. */ - if (!loop || loop->inner) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "not innermost loop\n"); - return false; - } - - /* If only one block, no need for if-conversion. */ - if (loop->num_nodes <= 2) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "less than 2 basic blocks\n"); - return false; - } - - /* More than one loop exit is too much to handle. */ - if (!single_exit (loop)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "multiple exits\n"); - return false; - } - - /* If one of the loop header's edge is an exit edge then do not - apply if-conversion. */ - FOR_EACH_EDGE (e, ei, loop->header->succs) - if (loop_exit_edge_p (loop, e)) - return false; - - refs.create (5); - res = if_convertible_loop_p_1 (loop, &refs); - - data_reference_p dr; - unsigned int i; - for (i = 0; refs.iterate (i, &dr); i++) - free (dr->aux); - - free_data_refs (refs); - - delete innermost_DR_map; - innermost_DR_map = NULL; - - delete baseref_DR_map; - baseref_DR_map = NULL; - - return res; -} - -/* Return reduc_1 if has_nop. - - if (...) - tmp1 = (unsigned type) reduc_1; - tmp2 = tmp1 + rhs2; - reduc_3 = (signed type) tmp2. */ -static tree -strip_nop_cond_scalar_reduction (bool has_nop, tree op) -{ - if (!has_nop) - return op; - - if (TREE_CODE (op) != SSA_NAME) - return NULL_TREE; - - gassign *stmt = safe_dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op)); - if (!stmt - || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt)) - || !tree_nop_conversion_p (TREE_TYPE (op), TREE_TYPE - (gimple_assign_rhs1 (stmt)))) - return NULL_TREE; - - return gimple_assign_rhs1 (stmt); -} - -/* Returns true if def-stmt for phi argument ARG is simple increment/decrement - which is in predicated basic block. - In fact, the following PHI pattern is searching: - loop-header: - reduc_1 = PHI <..., reduc_2> - ... - if (...) - reduc_3 = ... - reduc_2 = PHI <reduc_1, reduc_3> - - ARG_0 and ARG_1 are correspondent PHI arguments. - REDUC, OP0 and OP1 contain reduction stmt and its operands. - EXTENDED is true if PHI has > 2 arguments. */ - -static bool -is_cond_scalar_reduction (gimple *phi, gimple **reduc, tree arg_0, tree arg_1, - tree *op0, tree *op1, bool extended, bool* has_nop, - gimple **nop_reduc) -{ - tree lhs, r_op1, r_op2, r_nop1, r_nop2; - gimple *stmt; - gimple *header_phi = NULL; - enum tree_code reduction_op; - basic_block bb = gimple_bb (phi); - class loop *loop = bb->loop_father; - edge latch_e = loop_latch_edge (loop); - imm_use_iterator imm_iter; - use_operand_p use_p; - edge e; - edge_iterator ei; - bool result = *has_nop = false; - if (TREE_CODE (arg_0) != SSA_NAME || TREE_CODE (arg_1) != SSA_NAME) - return false; - - if (!extended && gimple_code (SSA_NAME_DEF_STMT (arg_0)) == GIMPLE_PHI) - { - lhs = arg_1; - header_phi = SSA_NAME_DEF_STMT (arg_0); - stmt = SSA_NAME_DEF_STMT (arg_1); - } - else if (gimple_code (SSA_NAME_DEF_STMT (arg_1)) == GIMPLE_PHI) - { - lhs = arg_0; - header_phi = SSA_NAME_DEF_STMT (arg_1); - stmt = SSA_NAME_DEF_STMT (arg_0); - } - else - return false; - if (gimple_bb (header_phi) != loop->header) - return false; - - if (PHI_ARG_DEF_FROM_EDGE (header_phi, latch_e) != PHI_RESULT (phi)) - return false; - - if (gimple_code (stmt) != GIMPLE_ASSIGN - || gimple_has_volatile_ops (stmt)) - return false; - - if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt))) - return false; - - if (!is_predicated (gimple_bb (stmt))) - return false; - - /* Check that stmt-block is predecessor of phi-block. */ - FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs) - if (e->dest == bb) - { - result = true; - break; - } - if (!result) - return false; - - if (!has_single_use (lhs)) - return false; - - reduction_op = gimple_assign_rhs_code (stmt); - - /* Catch something like below - - loop-header: - reduc_1 = PHI <..., reduc_2> - ... - if (...) - tmp1 = (unsigned type) reduc_1; - tmp2 = tmp1 + rhs2; - reduc_3 = (signed type) tmp2; - - reduc_2 = PHI <reduc_1, reduc_3> - - and convert to - - reduc_2 = PHI <0, reduc_3> - tmp1 = (unsigned type)reduce_1; - ifcvt = cond_expr ? rhs2 : 0 - tmp2 = tmp1 +/- ifcvt; - reduce_1 = (signed type)tmp2; */ - - if (CONVERT_EXPR_CODE_P (reduction_op)) - { - lhs = gimple_assign_rhs1 (stmt); - if (TREE_CODE (lhs) != SSA_NAME - || !has_single_use (lhs)) - return false; - - *nop_reduc = stmt; - stmt = SSA_NAME_DEF_STMT (lhs); - if (gimple_bb (stmt) != gimple_bb (*nop_reduc) - || !is_gimple_assign (stmt)) - return false; - - *has_nop = true; - reduction_op = gimple_assign_rhs_code (stmt); - } - - if (reduction_op != PLUS_EXPR - && reduction_op != MINUS_EXPR - && reduction_op != BIT_IOR_EXPR - && reduction_op != BIT_XOR_EXPR - && reduction_op != BIT_AND_EXPR) - return false; - r_op1 = gimple_assign_rhs1 (stmt); - r_op2 = gimple_assign_rhs2 (stmt); - - r_nop1 = strip_nop_cond_scalar_reduction (*has_nop, r_op1); - r_nop2 = strip_nop_cond_scalar_reduction (*has_nop, r_op2); - - /* Make R_OP1 to hold reduction variable. */ - if (r_nop2 == PHI_RESULT (header_phi) - && commutative_tree_code (reduction_op)) - { - std::swap (r_op1, r_op2); - std::swap (r_nop1, r_nop2); - } - else if (r_nop1 != PHI_RESULT (header_phi)) - return false; - - if (*has_nop) - { - /* Check that R_NOP1 is used in nop_stmt or in PHI only. */ - FOR_EACH_IMM_USE_FAST (use_p, imm_iter, r_nop1) - { - gimple *use_stmt = USE_STMT (use_p); - if (is_gimple_debug (use_stmt)) - continue; - if (use_stmt == SSA_NAME_DEF_STMT (r_op1)) - continue; - if (use_stmt != phi) - return false; - } - } - - /* Check that R_OP1 is used in reduction stmt or in PHI only. */ - FOR_EACH_IMM_USE_FAST (use_p, imm_iter, r_op1) - { - gimple *use_stmt = USE_STMT (use_p); - if (is_gimple_debug (use_stmt)) - continue; - if (use_stmt == stmt) - continue; - if (gimple_code (use_stmt) != GIMPLE_PHI) - return false; - } - - *op0 = r_op1; *op1 = r_op2; - *reduc = stmt; - return true; -} - -/* Converts conditional scalar reduction into unconditional form, e.g. - bb_4 - if (_5 != 0) goto bb_5 else goto bb_6 - end_bb_4 - bb_5 - res_6 = res_13 + 1; - end_bb_5 - bb_6 - # res_2 = PHI <res_13(4), res_6(5)> - end_bb_6 - - will be converted into sequence - _ifc__1 = _5 != 0 ? 1 : 0; - res_2 = res_13 + _ifc__1; - Argument SWAP tells that arguments of conditional expression should be - swapped. - Returns rhs of resulting PHI assignment. */ - -static tree -convert_scalar_cond_reduction (gimple *reduc, gimple_stmt_iterator *gsi, - tree cond, tree op0, tree op1, bool swap, - bool has_nop, gimple* nop_reduc) -{ - gimple_stmt_iterator stmt_it; - gimple *new_assign; - tree rhs; - tree rhs1 = gimple_assign_rhs1 (reduc); - tree tmp = make_temp_ssa_name (TREE_TYPE (rhs1), NULL, "_ifc_"); - tree c; - enum tree_code reduction_op = gimple_assign_rhs_code (reduc); - tree op_nochange = neutral_op_for_reduction (TREE_TYPE (rhs1), reduction_op, NULL); - gimple_seq stmts = NULL; - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "Found cond scalar reduction.\n"); - print_gimple_stmt (dump_file, reduc, 0, TDF_SLIM); - } - - /* Build cond expression using COND and constant operand - of reduction rhs. */ - c = fold_build_cond_expr (TREE_TYPE (rhs1), - unshare_expr (cond), - swap ? op_nochange : op1, - swap ? op1 : op_nochange); - - /* Create assignment stmt and insert it at GSI. */ - new_assign = gimple_build_assign (tmp, c); - gsi_insert_before (gsi, new_assign, GSI_SAME_STMT); - /* Build rhs for unconditional increment/decrement/logic_operation. */ - rhs = gimple_build (&stmts, reduction_op, - TREE_TYPE (rhs1), op0, tmp); - - if (has_nop) - { - rhs = gimple_convert (&stmts, - TREE_TYPE (gimple_assign_lhs (nop_reduc)), rhs); - stmt_it = gsi_for_stmt (nop_reduc); - gsi_remove (&stmt_it, true); - release_defs (nop_reduc); - } - gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); - - /* Delete original reduction stmt. */ - stmt_it = gsi_for_stmt (reduc); - gsi_remove (&stmt_it, true); - release_defs (reduc); - return rhs; -} - -/* Produce condition for all occurrences of ARG in PHI node. */ - -static tree -gen_phi_arg_condition (gphi *phi, vec<int> *occur, - gimple_stmt_iterator *gsi) -{ - int len; - int i; - tree cond = NULL_TREE; - tree c; - edge e; - - len = occur->length (); - gcc_assert (len > 0); - for (i = 0; i < len; i++) - { - e = gimple_phi_arg_edge (phi, (*occur)[i]); - c = bb_predicate (e->src); - if (is_true_predicate (c)) - { - cond = c; - break; - } - c = force_gimple_operand_gsi_1 (gsi, unshare_expr (c), - is_gimple_condexpr, NULL_TREE, - true, GSI_SAME_STMT); - if (cond != NULL_TREE) - { - /* Must build OR expression. */ - cond = fold_or_predicates (EXPR_LOCATION (c), c, cond); - cond = force_gimple_operand_gsi_1 (gsi, unshare_expr (cond), - is_gimple_condexpr, NULL_TREE, - true, GSI_SAME_STMT); - } - else - cond = c; - } - gcc_assert (cond != NULL_TREE); - return cond; -} - -/* Local valueization callback that follows all-use SSA edges. */ - -static tree -ifcvt_follow_ssa_use_edges (tree val) -{ - return val; -} - -/* Replace a scalar PHI node with a COND_EXPR using COND as condition. - This routine can handle PHI nodes with more than two arguments. - - For example, - S1: A = PHI <x1(1), x2(5)> - is converted into, - S2: A = cond ? x1 : x2; - - The generated code is inserted at GSI that points to the top of - basic block's statement list. - If PHI node has more than two arguments a chain of conditional - expression is produced. */ - - -static void -predicate_scalar_phi (gphi *phi, gimple_stmt_iterator *gsi) -{ - gimple *new_stmt = NULL, *reduc, *nop_reduc; - tree rhs, res, arg0, arg1, op0, op1, scev; - tree cond; - unsigned int index0; - unsigned int max, args_len; - edge e; - basic_block bb; - unsigned int i; - bool has_nop; - - res = gimple_phi_result (phi); - if (virtual_operand_p (res)) - return; - - if ((rhs = degenerate_phi_result (phi)) - || ((scev = analyze_scalar_evolution (gimple_bb (phi)->loop_father, - res)) - && !chrec_contains_undetermined (scev) - && scev != res - && (rhs = gimple_phi_arg_def (phi, 0)))) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "Degenerate phi!\n"); - print_gimple_stmt (dump_file, phi, 0, TDF_SLIM); - } - new_stmt = gimple_build_assign (res, rhs); - gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); - update_stmt (new_stmt); - return; - } - - bb = gimple_bb (phi); - if (EDGE_COUNT (bb->preds) == 2) - { - /* Predicate ordinary PHI node with 2 arguments. */ - edge first_edge, second_edge; - basic_block true_bb; - first_edge = EDGE_PRED (bb, 0); - second_edge = EDGE_PRED (bb, 1); - cond = bb_predicate (first_edge->src); - if (TREE_CODE (cond) == TRUTH_NOT_EXPR) - std::swap (first_edge, second_edge); - if (EDGE_COUNT (first_edge->src->succs) > 1) - { - cond = bb_predicate (second_edge->src); - if (TREE_CODE (cond) == TRUTH_NOT_EXPR) - cond = TREE_OPERAND (cond, 0); - else - first_edge = second_edge; - } - else - cond = bb_predicate (first_edge->src); - /* Gimplify the condition to a valid cond-expr conditonal operand. */ - cond = force_gimple_operand_gsi_1 (gsi, unshare_expr (cond), - is_gimple_condexpr, NULL_TREE, - true, GSI_SAME_STMT); - true_bb = first_edge->src; - if (EDGE_PRED (bb, 1)->src == true_bb) - { - arg0 = gimple_phi_arg_def (phi, 1); - arg1 = gimple_phi_arg_def (phi, 0); - } - else - { - arg0 = gimple_phi_arg_def (phi, 0); - arg1 = gimple_phi_arg_def (phi, 1); - } - if (is_cond_scalar_reduction (phi, &reduc, arg0, arg1, - &op0, &op1, false, &has_nop, - &nop_reduc)) - { - /* Convert reduction stmt into vectorizable form. */ - rhs = convert_scalar_cond_reduction (reduc, gsi, cond, op0, op1, - true_bb != gimple_bb (reduc), - has_nop, nop_reduc); - redundant_ssa_names.safe_push (std::make_pair (res, rhs)); - } - else - /* Build new RHS using selected condition and arguments. */ - rhs = fold_build_cond_expr (TREE_TYPE (res), unshare_expr (cond), - arg0, arg1); - new_stmt = gimple_build_assign (res, rhs); - gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); - gimple_stmt_iterator new_gsi = gsi_for_stmt (new_stmt); - if (fold_stmt (&new_gsi, ifcvt_follow_ssa_use_edges)) - { - new_stmt = gsi_stmt (new_gsi); - update_stmt (new_stmt); - } - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "new phi replacement stmt\n"); - print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM); - } - return; - } - - /* Create hashmap for PHI node which contain vector of argument indexes - having the same value. */ - bool swap = false; - hash_map<tree_operand_hash, auto_vec<int> > phi_arg_map; - unsigned int num_args = gimple_phi_num_args (phi); - int max_ind = -1; - /* Vector of different PHI argument values. */ - auto_vec<tree> args (num_args); - - /* Compute phi_arg_map. */ - for (i = 0; i < num_args; i++) - { - tree arg; - - arg = gimple_phi_arg_def (phi, i); - if (!phi_arg_map.get (arg)) - args.quick_push (arg); - phi_arg_map.get_or_insert (arg).safe_push (i); - } - - /* Determine element with max number of occurrences. */ - max_ind = -1; - max = 1; - args_len = args.length (); - for (i = 0; i < args_len; i++) - { - unsigned int len; - if ((len = phi_arg_map.get (args[i])->length ()) > max) - { - max_ind = (int) i; - max = len; - } - } - - /* Put element with max number of occurences to the end of ARGS. */ - if (max_ind != -1 && max_ind +1 != (int) args_len) - std::swap (args[args_len - 1], args[max_ind]); - - /* Handle one special case when number of arguments with different values - is equal 2 and one argument has the only occurrence. Such PHI can be - handled as if would have only 2 arguments. */ - if (args_len == 2 && phi_arg_map.get (args[0])->length () == 1) - { - vec<int> *indexes; - indexes = phi_arg_map.get (args[0]); - index0 = (*indexes)[0]; - arg0 = args[0]; - arg1 = args[1]; - e = gimple_phi_arg_edge (phi, index0); - cond = bb_predicate (e->src); - if (TREE_CODE (cond) == TRUTH_NOT_EXPR) - { - swap = true; - cond = TREE_OPERAND (cond, 0); - } - /* Gimplify the condition to a valid cond-expr conditonal operand. */ - cond = force_gimple_operand_gsi_1 (gsi, unshare_expr (cond), - is_gimple_condexpr, NULL_TREE, - true, GSI_SAME_STMT); - if (!(is_cond_scalar_reduction (phi, &reduc, arg0 , arg1, - &op0, &op1, true, &has_nop, &nop_reduc))) - rhs = fold_build_cond_expr (TREE_TYPE (res), unshare_expr (cond), - swap? arg1 : arg0, - swap? arg0 : arg1); - else - { - /* Convert reduction stmt into vectorizable form. */ - rhs = convert_scalar_cond_reduction (reduc, gsi, cond, op0, op1, - swap,has_nop, nop_reduc); - redundant_ssa_names.safe_push (std::make_pair (res, rhs)); - } - new_stmt = gimple_build_assign (res, rhs); - gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); - update_stmt (new_stmt); - } - else - { - /* Common case. */ - vec<int> *indexes; - tree type = TREE_TYPE (gimple_phi_result (phi)); - tree lhs; - arg1 = args[1]; - for (i = 0; i < args_len; i++) - { - arg0 = args[i]; - indexes = phi_arg_map.get (args[i]); - if (i != args_len - 1) - lhs = make_temp_ssa_name (type, NULL, "_ifc_"); - else - lhs = res; - cond = gen_phi_arg_condition (phi, indexes, gsi); - rhs = fold_build_cond_expr (type, unshare_expr (cond), - arg0, arg1); - new_stmt = gimple_build_assign (lhs, rhs); - gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); - update_stmt (new_stmt); - arg1 = lhs; - } - } - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "new extended phi replacement stmt\n"); - print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM); - } -} - -/* Replaces in LOOP all the scalar phi nodes other than those in the - LOOP->header block with conditional modify expressions. */ - -static void -predicate_all_scalar_phis (class loop *loop) -{ - basic_block bb; - unsigned int orig_loop_num_nodes = loop->num_nodes; - unsigned int i; - - for (i = 1; i < orig_loop_num_nodes; i++) - { - gphi *phi; - gimple_stmt_iterator gsi; - gphi_iterator phi_gsi; - bb = ifc_bbs[i]; - - if (bb == loop->header) - continue; - - phi_gsi = gsi_start_phis (bb); - if (gsi_end_p (phi_gsi)) - continue; - - gsi = gsi_after_labels (bb); - while (!gsi_end_p (phi_gsi)) - { - phi = phi_gsi.phi (); - if (virtual_operand_p (gimple_phi_result (phi))) - gsi_next (&phi_gsi); - else - { - predicate_scalar_phi (phi, &gsi); - remove_phi_node (&phi_gsi, false); - } - } - } -} - -/* Insert in each basic block of LOOP the statements produced by the - gimplification of the predicates. */ - -static void -insert_gimplified_predicates (loop_p loop) -{ - unsigned int i; - - for (i = 0; i < loop->num_nodes; i++) - { - basic_block bb = ifc_bbs[i]; - gimple_seq stmts; - if (!is_predicated (bb)) - gcc_assert (bb_predicate_gimplified_stmts (bb) == NULL); - if (!is_predicated (bb)) - { - /* Do not insert statements for a basic block that is not - predicated. Also make sure that the predicate of the - basic block is set to true. */ - reset_bb_predicate (bb); - continue; - } - - stmts = bb_predicate_gimplified_stmts (bb); - if (stmts) - { - if (need_to_predicate) - { - /* Insert the predicate of the BB just after the label, - as the if-conversion of memory writes will use this - predicate. */ - gimple_stmt_iterator gsi = gsi_after_labels (bb); - gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT); - } - else - { - /* Insert the predicate of the BB at the end of the BB - as this would reduce the register pressure: the only - use of this predicate will be in successor BBs. */ - gimple_stmt_iterator gsi = gsi_last_bb (bb); - - if (gsi_end_p (gsi) - || stmt_ends_bb_p (gsi_stmt (gsi))) - gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT); - else - gsi_insert_seq_after (&gsi, stmts, GSI_SAME_STMT); - } - - /* Once the sequence is code generated, set it to NULL. */ - set_bb_predicate_gimplified_stmts (bb, NULL); - } - } -} - -/* Helper function for predicate_statements. Returns index of existent - mask if it was created for given SIZE and -1 otherwise. */ - -static int -mask_exists (int size, const vec<int> &vec) -{ - unsigned int ix; - int v; - FOR_EACH_VEC_ELT (vec, ix, v) - if (v == size) - return (int) ix; - return -1; -} - -/* Helper function for predicate_statements. STMT is a memory read or - write and it needs to be predicated by MASK. Return a statement - that does so. */ - -static gimple * -predicate_load_or_store (gimple_stmt_iterator *gsi, gassign *stmt, tree mask) -{ - gcall *new_stmt; - - tree lhs = gimple_assign_lhs (stmt); - tree rhs = gimple_assign_rhs1 (stmt); - tree ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs; - mark_addressable (ref); - tree addr = force_gimple_operand_gsi (gsi, build_fold_addr_expr (ref), - true, NULL_TREE, true, GSI_SAME_STMT); - tree ptr = build_int_cst (reference_alias_ptr_type (ref), - get_object_alignment (ref)); - /* Copy points-to info if possible. */ - if (TREE_CODE (addr) == SSA_NAME && !SSA_NAME_PTR_INFO (addr)) - copy_ref_info (build2 (MEM_REF, TREE_TYPE (ref), addr, ptr), - ref); - if (TREE_CODE (lhs) == SSA_NAME) - { - new_stmt - = gimple_build_call_internal (IFN_MASK_LOAD, 3, addr, - ptr, mask); - gimple_call_set_lhs (new_stmt, lhs); - gimple_set_vuse (new_stmt, gimple_vuse (stmt)); - } - else - { - new_stmt - = gimple_build_call_internal (IFN_MASK_STORE, 4, addr, ptr, - mask, rhs); - gimple_move_vops (new_stmt, stmt); - } - gimple_call_set_nothrow (new_stmt, true); - return new_stmt; -} - -/* STMT uses OP_LHS. Check whether it is equivalent to: - - ... = OP_MASK ? OP_LHS : X; - - Return X if so, otherwise return null. OP_MASK is an SSA_NAME that is - known to have value OP_COND. */ - -static tree -check_redundant_cond_expr (gimple *stmt, tree op_mask, tree op_cond, - tree op_lhs) -{ - gassign *assign = dyn_cast <gassign *> (stmt); - if (!assign || gimple_assign_rhs_code (assign) != COND_EXPR) - return NULL_TREE; - - tree use_cond = gimple_assign_rhs1 (assign); - tree if_true = gimple_assign_rhs2 (assign); - tree if_false = gimple_assign_rhs3 (assign); - - if ((use_cond == op_mask || operand_equal_p (use_cond, op_cond, 0)) - && if_true == op_lhs) - return if_false; - - if (inverse_conditions_p (use_cond, op_cond) && if_false == op_lhs) - return if_true; - - return NULL_TREE; -} - -/* Return true if VALUE is available for use at STMT. SSA_NAMES is - the set of SSA names defined earlier in STMT's block. */ - -static bool -value_available_p (gimple *stmt, hash_set<tree_ssa_name_hash> *ssa_names, - tree value) -{ - if (is_gimple_min_invariant (value)) - return true; - - if (TREE_CODE (value) == SSA_NAME) - { - if (SSA_NAME_IS_DEFAULT_DEF (value)) - return true; - - basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (value)); - basic_block use_bb = gimple_bb (stmt); - return (def_bb == use_bb - ? ssa_names->contains (value) - : dominated_by_p (CDI_DOMINATORS, use_bb, def_bb)); - } - - return false; -} - -/* Helper function for predicate_statements. STMT is a potentially-trapping - arithmetic operation that needs to be predicated by MASK, an SSA_NAME that - has value COND. Return a statement that does so. SSA_NAMES is the set of - SSA names defined earlier in STMT's block. */ - -static gimple * -predicate_rhs_code (gassign *stmt, tree mask, tree cond, - hash_set<tree_ssa_name_hash> *ssa_names) -{ - tree lhs = gimple_assign_lhs (stmt); - tree_code code = gimple_assign_rhs_code (stmt); - unsigned int nops = gimple_num_ops (stmt); - internal_fn cond_fn = get_conditional_internal_fn (code); - - /* Construct the arguments to the conditional internal function. */ - auto_vec<tree, 8> args; - args.safe_grow (nops + 1, true); - args[0] = mask; - for (unsigned int i = 1; i < nops; ++i) - args[i] = gimple_op (stmt, i); - args[nops] = NULL_TREE; - - /* Look for uses of the result to see whether they are COND_EXPRs that can - be folded into the conditional call. */ - imm_use_iterator imm_iter; - gimple *use_stmt; - FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, lhs) - { - tree new_else = check_redundant_cond_expr (use_stmt, mask, cond, lhs); - if (new_else && value_available_p (stmt, ssa_names, new_else)) - { - if (!args[nops]) - args[nops] = new_else; - if (operand_equal_p (new_else, args[nops], 0)) - { - /* We have: - - LHS = IFN_COND (MASK, ..., ELSE); - X = MASK ? LHS : ELSE; - - which makes X equivalent to LHS. */ - tree use_lhs = gimple_assign_lhs (use_stmt); - redundant_ssa_names.safe_push (std::make_pair (use_lhs, lhs)); - } - } - } - if (!args[nops]) - args[nops] = targetm.preferred_else_value (cond_fn, TREE_TYPE (lhs), - nops - 1, &args[1]); - - /* Create and insert the call. */ - gcall *new_stmt = gimple_build_call_internal_vec (cond_fn, args); - gimple_call_set_lhs (new_stmt, lhs); - gimple_call_set_nothrow (new_stmt, true); - - return new_stmt; -} - -/* Predicate each write to memory in LOOP. - - This function transforms control flow constructs containing memory - writes of the form: - - | for (i = 0; i < N; i++) - | if (cond) - | A[i] = expr; - - into the following form that does not contain control flow: - - | for (i = 0; i < N; i++) - | A[i] = cond ? expr : A[i]; - - The original CFG looks like this: - - | bb_0 - | i = 0 - | end_bb_0 - | - | bb_1 - | if (i < N) goto bb_5 else goto bb_2 - | end_bb_1 - | - | bb_2 - | cond = some_computation; - | if (cond) goto bb_3 else goto bb_4 - | end_bb_2 - | - | bb_3 - | A[i] = expr; - | goto bb_4 - | end_bb_3 - | - | bb_4 - | goto bb_1 - | end_bb_4 - - insert_gimplified_predicates inserts the computation of the COND - expression at the beginning of the destination basic block: - - | bb_0 - | i = 0 - | end_bb_0 - | - | bb_1 - | if (i < N) goto bb_5 else goto bb_2 - | end_bb_1 - | - | bb_2 - | cond = some_computation; - | if (cond) goto bb_3 else goto bb_4 - | end_bb_2 - | - | bb_3 - | cond = some_computation; - | A[i] = expr; - | goto bb_4 - | end_bb_3 - | - | bb_4 - | goto bb_1 - | end_bb_4 - - predicate_statements is then predicating the memory write as follows: - - | bb_0 - | i = 0 - | end_bb_0 - | - | bb_1 - | if (i < N) goto bb_5 else goto bb_2 - | end_bb_1 - | - | bb_2 - | if (cond) goto bb_3 else goto bb_4 - | end_bb_2 - | - | bb_3 - | cond = some_computation; - | A[i] = cond ? expr : A[i]; - | goto bb_4 - | end_bb_3 - | - | bb_4 - | goto bb_1 - | end_bb_4 - - and finally combine_blocks removes the basic block boundaries making - the loop vectorizable: - - | bb_0 - | i = 0 - | if (i < N) goto bb_5 else goto bb_1 - | end_bb_0 - | - | bb_1 - | cond = some_computation; - | A[i] = cond ? expr : A[i]; - | if (i < N) goto bb_5 else goto bb_4 - | end_bb_1 - | - | bb_4 - | goto bb_1 - | end_bb_4 -*/ - -static void -predicate_statements (loop_p loop) -{ - unsigned int i, orig_loop_num_nodes = loop->num_nodes; - auto_vec<int, 1> vect_sizes; - auto_vec<tree, 1> vect_masks; - hash_set<tree_ssa_name_hash> ssa_names; - - for (i = 1; i < orig_loop_num_nodes; i++) - { - gimple_stmt_iterator gsi; - basic_block bb = ifc_bbs[i]; - tree cond = bb_predicate (bb); - bool swap; - int index; - - if (is_true_predicate (cond)) - continue; - - swap = false; - if (TREE_CODE (cond) == TRUTH_NOT_EXPR) - { - swap = true; - cond = TREE_OPERAND (cond, 0); - } - - vect_sizes.truncate (0); - vect_masks.truncate (0); - - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);) - { - gassign *stmt = dyn_cast <gassign *> (gsi_stmt (gsi)); - tree lhs; - if (!stmt) - ; - else if (is_false_predicate (cond) - && gimple_vdef (stmt)) - { - unlink_stmt_vdef (stmt); - gsi_remove (&gsi, true); - release_defs (stmt); - continue; - } - else if (gimple_plf (stmt, GF_PLF_2)) - { - tree lhs = gimple_assign_lhs (stmt); - tree mask; - gimple *new_stmt; - gimple_seq stmts = NULL; - machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); - /* We checked before setting GF_PLF_2 that an equivalent - integer mode exists. */ - int bitsize = GET_MODE_BITSIZE (mode).to_constant (); - if (!vect_sizes.is_empty () - && (index = mask_exists (bitsize, vect_sizes)) != -1) - /* Use created mask. */ - mask = vect_masks[index]; - else - { - if (COMPARISON_CLASS_P (cond)) - mask = gimple_build (&stmts, TREE_CODE (cond), - boolean_type_node, - TREE_OPERAND (cond, 0), - TREE_OPERAND (cond, 1)); - else - mask = cond; - - if (swap) - { - tree true_val - = constant_boolean_node (true, TREE_TYPE (mask)); - mask = gimple_build (&stmts, BIT_XOR_EXPR, - TREE_TYPE (mask), mask, true_val); - } - gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT); - - /* Save mask and its size for further use. */ - vect_sizes.safe_push (bitsize); - vect_masks.safe_push (mask); - } - if (gimple_assign_single_p (stmt)) - new_stmt = predicate_load_or_store (&gsi, stmt, mask); - else - new_stmt = predicate_rhs_code (stmt, mask, cond, &ssa_names); - - gsi_replace (&gsi, new_stmt, true); - } - else if (((lhs = gimple_assign_lhs (stmt)), true) - && (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) - || POINTER_TYPE_P (TREE_TYPE (lhs))) - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs)) - && arith_code_with_undefined_signed_overflow - (gimple_assign_rhs_code (stmt))) - { - gsi_remove (&gsi, true); - gimple_seq stmts = rewrite_to_defined_overflow (stmt); - bool first = true; - for (gimple_stmt_iterator gsi2 = gsi_start (stmts); - !gsi_end_p (gsi2);) - { - gassign *stmt2 = as_a <gassign *> (gsi_stmt (gsi2)); - gsi_remove (&gsi2, false); - if (first) - { - gsi_insert_before (&gsi, stmt2, GSI_NEW_STMT); - first = false; - } - else - gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT); - } - } - else if (gimple_vdef (stmt)) - { - tree lhs = gimple_assign_lhs (stmt); - tree rhs = gimple_assign_rhs1 (stmt); - tree type = TREE_TYPE (lhs); - - lhs = ifc_temp_var (type, unshare_expr (lhs), &gsi); - rhs = ifc_temp_var (type, unshare_expr (rhs), &gsi); - if (swap) - std::swap (lhs, rhs); - cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond), - is_gimple_condexpr, NULL_TREE, - true, GSI_SAME_STMT); - rhs = fold_build_cond_expr (type, unshare_expr (cond), rhs, lhs); - gimple_assign_set_rhs1 (stmt, ifc_temp_var (type, rhs, &gsi)); - update_stmt (stmt); - } - lhs = gimple_get_lhs (gsi_stmt (gsi)); - if (lhs && TREE_CODE (lhs) == SSA_NAME) - ssa_names.add (lhs); - gsi_next (&gsi); - } - ssa_names.empty (); - } -} - -/* Remove all GIMPLE_CONDs and GIMPLE_LABELs of all the basic blocks - other than the exit and latch of the LOOP. Also resets the - GIMPLE_DEBUG information. */ - -static void -remove_conditions_and_labels (loop_p loop) -{ - gimple_stmt_iterator gsi; - unsigned int i; - - for (i = 0; i < loop->num_nodes; i++) - { - basic_block bb = ifc_bbs[i]; - - if (bb_with_exit_edge_p (loop, bb) - || bb == loop->latch) - continue; - - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); ) - switch (gimple_code (gsi_stmt (gsi))) - { - case GIMPLE_COND: - case GIMPLE_LABEL: - gsi_remove (&gsi, true); - break; - - case GIMPLE_DEBUG: - /* ??? Should there be conditional GIMPLE_DEBUG_BINDs? */ - if (gimple_debug_bind_p (gsi_stmt (gsi))) - { - gimple_debug_bind_reset_value (gsi_stmt (gsi)); - update_stmt (gsi_stmt (gsi)); - } - gsi_next (&gsi); - break; - - default: - gsi_next (&gsi); - } - } -} - -/* Combine all the basic blocks from LOOP into one or two super basic - blocks. Replace PHI nodes with conditional modify expressions. */ - -static void -combine_blocks (class loop *loop) -{ - basic_block bb, exit_bb, merge_target_bb; - unsigned int orig_loop_num_nodes = loop->num_nodes; - unsigned int i; - edge e; - edge_iterator ei; - - remove_conditions_and_labels (loop); - insert_gimplified_predicates (loop); - predicate_all_scalar_phis (loop); - - if (need_to_predicate || need_to_rewrite_undefined) - predicate_statements (loop); - - /* Merge basic blocks. */ - exit_bb = NULL; - bool *predicated = XNEWVEC (bool, orig_loop_num_nodes); - for (i = 0; i < orig_loop_num_nodes; i++) - { - bb = ifc_bbs[i]; - predicated[i] = !is_true_predicate (bb_predicate (bb)); - free_bb_predicate (bb); - if (bb_with_exit_edge_p (loop, bb)) - { - gcc_assert (exit_bb == NULL); - exit_bb = bb; - } - } - gcc_assert (exit_bb != loop->latch); - - merge_target_bb = loop->header; - - /* Get at the virtual def valid for uses starting at the first block - we merge into the header. Without a virtual PHI the loop has the - same virtual use on all stmts. */ - gphi *vphi = get_virtual_phi (loop->header); - tree last_vdef = NULL_TREE; - if (vphi) - { - last_vdef = gimple_phi_result (vphi); - for (gimple_stmt_iterator gsi = gsi_start_bb (loop->header); - ! gsi_end_p (gsi); gsi_next (&gsi)) - if (gimple_vdef (gsi_stmt (gsi))) - last_vdef = gimple_vdef (gsi_stmt (gsi)); - } - for (i = 1; i < orig_loop_num_nodes; i++) - { - gimple_stmt_iterator gsi; - gimple_stmt_iterator last; - - bb = ifc_bbs[i]; - - if (bb == exit_bb || bb == loop->latch) - continue; - - /* We release virtual PHIs late because we have to propagate them - out using the current VUSE. The def might be the one used - after the loop. */ - vphi = get_virtual_phi (bb); - if (vphi) - { - /* When there's just loads inside the loop a stray virtual - PHI merging the uses can appear, update last_vdef from - it. */ - if (!last_vdef) - last_vdef = gimple_phi_arg_def (vphi, 0); - imm_use_iterator iter; - use_operand_p use_p; - gimple *use_stmt; - FOR_EACH_IMM_USE_STMT (use_stmt, iter, gimple_phi_result (vphi)) - { - FOR_EACH_IMM_USE_ON_STMT (use_p, iter) - SET_USE (use_p, last_vdef); - } - if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (vphi))) - SSA_NAME_OCCURS_IN_ABNORMAL_PHI (last_vdef) = 1; - gsi = gsi_for_stmt (vphi); - remove_phi_node (&gsi, true); - } - - /* Make stmts member of loop->header and clear range info from all stmts - in BB which is now no longer executed conditional on a predicate we - could have derived it from. */ - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple *stmt = gsi_stmt (gsi); - gimple_set_bb (stmt, merge_target_bb); - /* Update virtual operands. */ - if (last_vdef) - { - use_operand_p use_p = ssa_vuse_operand (stmt); - if (use_p - && USE_FROM_PTR (use_p) != last_vdef) - SET_USE (use_p, last_vdef); - if (gimple_vdef (stmt)) - last_vdef = gimple_vdef (stmt); - } - else - /* If this is the first load we arrive at update last_vdef - so we handle stray PHIs correctly. */ - last_vdef = gimple_vuse (stmt); - if (predicated[i]) - { - ssa_op_iter i; - tree op; - FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_DEF) - reset_flow_sensitive_info (op); - } - } - - /* Update stmt list. */ - last = gsi_last_bb (merge_target_bb); - gsi_insert_seq_after_without_update (&last, bb_seq (bb), GSI_NEW_STMT); - set_bb_seq (bb, NULL); - } - - /* Fixup virtual operands in the exit block. */ - if (exit_bb - && exit_bb != loop->header) - { - /* We release virtual PHIs late because we have to propagate them - out using the current VUSE. The def might be the one used - after the loop. */ - vphi = get_virtual_phi (exit_bb); - if (vphi) - { - /* When there's just loads inside the loop a stray virtual - PHI merging the uses can appear, update last_vdef from - it. */ - if (!last_vdef) - last_vdef = gimple_phi_arg_def (vphi, 0); - imm_use_iterator iter; - use_operand_p use_p; - gimple *use_stmt; - FOR_EACH_IMM_USE_STMT (use_stmt, iter, gimple_phi_result (vphi)) - { - FOR_EACH_IMM_USE_ON_STMT (use_p, iter) - SET_USE (use_p, last_vdef); - } - if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (vphi))) - SSA_NAME_OCCURS_IN_ABNORMAL_PHI (last_vdef) = 1; - gimple_stmt_iterator gsi = gsi_for_stmt (vphi); - remove_phi_node (&gsi, true); - } - } - - /* Now remove all the edges in the loop, except for those from the exit - block and delete the blocks we elided. */ - for (i = 1; i < orig_loop_num_nodes; i++) - { - bb = ifc_bbs[i]; - - for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));) - { - if (e->src == exit_bb) - ei_next (&ei); - else - remove_edge (e); - } - } - for (i = 1; i < orig_loop_num_nodes; i++) - { - bb = ifc_bbs[i]; - - if (bb == exit_bb || bb == loop->latch) - continue; - - delete_basic_block (bb); - } - - /* Re-connect the exit block. */ - if (exit_bb != NULL) - { - if (exit_bb != loop->header) - { - /* Connect this node to loop header. */ - make_single_succ_edge (loop->header, exit_bb, EDGE_FALLTHRU); - set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header); - } - - /* Redirect non-exit edges to loop->latch. */ - FOR_EACH_EDGE (e, ei, exit_bb->succs) - { - if (!loop_exit_edge_p (loop, e)) - redirect_edge_and_branch (e, loop->latch); - } - set_immediate_dominator (CDI_DOMINATORS, loop->latch, exit_bb); - } - else - { - /* If the loop does not have an exit, reconnect header and latch. */ - make_edge (loop->header, loop->latch, EDGE_FALLTHRU); - set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header); - } - - /* If possible, merge loop header to the block with the exit edge. - This reduces the number of basic blocks to two, to please the - vectorizer that handles only loops with two nodes. */ - if (exit_bb - && exit_bb != loop->header) - { - if (can_merge_blocks_p (loop->header, exit_bb)) - merge_blocks (loop->header, exit_bb); - } - - free (ifc_bbs); - ifc_bbs = NULL; - free (predicated); -} - -/* Version LOOP before if-converting it; the original loop - will be if-converted, the new copy of the loop will not, - and the LOOP_VECTORIZED internal call will be guarding which - loop to execute. The vectorizer pass will fold this - internal call into either true or false. - - Note that this function intentionally invalidates profile. Both edges - out of LOOP_VECTORIZED must have 100% probability so the profile remains - consistent after the condition is folded in the vectorizer. */ - -static class loop * -version_loop_for_if_conversion (class loop *loop, vec<gimple *> *preds) -{ - basic_block cond_bb; - tree cond = make_ssa_name (boolean_type_node); - class loop *new_loop; - gimple *g; - gimple_stmt_iterator gsi; - unsigned int save_length; - - g = gimple_build_call_internal (IFN_LOOP_VECTORIZED, 2, - build_int_cst (integer_type_node, loop->num), - integer_zero_node); - gimple_call_set_lhs (g, cond); - - /* Save BB->aux around loop_version as that uses the same field. */ - save_length = loop->inner ? loop->inner->num_nodes : loop->num_nodes; - void **saved_preds = XALLOCAVEC (void *, save_length); - for (unsigned i = 0; i < save_length; i++) - saved_preds[i] = ifc_bbs[i]->aux; - - initialize_original_copy_tables (); - /* At this point we invalidate porfile confistency until IFN_LOOP_VECTORIZED - is re-merged in the vectorizer. */ - new_loop = loop_version (loop, cond, &cond_bb, - profile_probability::always (), - profile_probability::always (), - profile_probability::always (), - profile_probability::always (), true); - free_original_copy_tables (); - - for (unsigned i = 0; i < save_length; i++) - ifc_bbs[i]->aux = saved_preds[i]; - - if (new_loop == NULL) - return NULL; - - new_loop->dont_vectorize = true; - new_loop->force_vectorize = false; - gsi = gsi_last_bb (cond_bb); - gimple_call_set_arg (g, 1, build_int_cst (integer_type_node, new_loop->num)); - if (preds) - preds->safe_push (g); - gsi_insert_before (&gsi, g, GSI_SAME_STMT); - update_ssa (TODO_update_ssa); - return new_loop; -} - -/* Return true when LOOP satisfies the follow conditions that will - allow it to be recognized by the vectorizer for outer-loop - vectorization: - - The loop is not the root node of the loop tree. - - The loop has exactly one inner loop. - - The loop has a single exit. - - The loop header has a single successor, which is the inner - loop header. - - Each of the inner and outer loop latches have a single - predecessor. - - The loop exit block has a single predecessor, which is the - inner loop's exit block. */ - -static bool -versionable_outer_loop_p (class loop *loop) -{ - if (!loop_outer (loop) - || loop->dont_vectorize - || !loop->inner - || loop->inner->next - || !single_exit (loop) - || !single_succ_p (loop->header) - || single_succ (loop->header) != loop->inner->header - || !single_pred_p (loop->latch) - || !single_pred_p (loop->inner->latch)) - return false; - - basic_block outer_exit = single_pred (loop->latch); - basic_block inner_exit = single_pred (loop->inner->latch); - - if (!single_pred_p (outer_exit) || single_pred (outer_exit) != inner_exit) - return false; - - if (dump_file) - fprintf (dump_file, "Found vectorizable outer loop for versioning\n"); - - return true; -} - -/* Performs splitting of critical edges. Skip splitting and return false - if LOOP will not be converted because: - - - LOOP is not well formed. - - LOOP has PHI with more than MAX_PHI_ARG_NUM arguments. - - Last restriction is valid only if AGGRESSIVE_IF_CONV is false. */ - -static bool -ifcvt_split_critical_edges (class loop *loop, bool aggressive_if_conv) -{ - basic_block *body; - basic_block bb; - unsigned int num = loop->num_nodes; - unsigned int i; - gimple *stmt; - edge e; - edge_iterator ei; - auto_vec<edge> critical_edges; - - /* Loop is not well formed. */ - if (num <= 2 || loop->inner || !single_exit (loop)) - return false; - - body = get_loop_body (loop); - for (i = 0; i < num; i++) - { - bb = body[i]; - if (!aggressive_if_conv - && phi_nodes (bb) - && EDGE_COUNT (bb->preds) > MAX_PHI_ARG_NUM) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, - "BB %d has complicated PHI with more than %u args.\n", - bb->index, MAX_PHI_ARG_NUM); - - free (body); - return false; - } - if (bb == loop->latch || bb_with_exit_edge_p (loop, bb)) - continue; - - stmt = last_stmt (bb); - /* Skip basic blocks not ending with conditional branch. */ - if (!stmt || gimple_code (stmt) != GIMPLE_COND) - continue; - - FOR_EACH_EDGE (e, ei, bb->succs) - if (EDGE_CRITICAL_P (e) && e->dest->loop_father == loop) - critical_edges.safe_push (e); - } - free (body); - - while (critical_edges.length () > 0) - { - e = critical_edges.pop (); - /* Don't split if bb can be predicated along non-critical edge. */ - if (EDGE_COUNT (e->dest->preds) > 2 || all_preds_critical_p (e->dest)) - split_edge (e); - } - - return true; -} - -/* Delete redundant statements produced by predication which prevents - loop vectorization. */ - -static void -ifcvt_local_dce (class loop *loop) -{ - gimple *stmt; - gimple *stmt1; - gimple *phi; - gimple_stmt_iterator gsi; - auto_vec<gimple *> worklist; - enum gimple_code code; - use_operand_p use_p; - imm_use_iterator imm_iter; - - /* The loop has a single BB only. */ - basic_block bb = loop->header; - tree latch_vdef = NULL_TREE; - - worklist.create (64); - /* Consider all phi as live statements. */ - for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - phi = gsi_stmt (gsi); - gimple_set_plf (phi, GF_PLF_2, true); - worklist.safe_push (phi); - if (virtual_operand_p (gimple_phi_result (phi))) - latch_vdef = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop)); - } - /* Consider load/store statements, CALL and COND as live. */ - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - stmt = gsi_stmt (gsi); - if (is_gimple_debug (stmt)) - { - gimple_set_plf (stmt, GF_PLF_2, true); - continue; - } - if (gimple_store_p (stmt) || gimple_assign_load_p (stmt)) - { - gimple_set_plf (stmt, GF_PLF_2, true); - worklist.safe_push (stmt); - continue; - } - code = gimple_code (stmt); - if (code == GIMPLE_COND || code == GIMPLE_CALL) - { - gimple_set_plf (stmt, GF_PLF_2, true); - worklist.safe_push (stmt); - continue; - } - gimple_set_plf (stmt, GF_PLF_2, false); - - if (code == GIMPLE_ASSIGN) - { - tree lhs = gimple_assign_lhs (stmt); - FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs) - { - stmt1 = USE_STMT (use_p); - if (!is_gimple_debug (stmt1) && gimple_bb (stmt1) != bb) - { - gimple_set_plf (stmt, GF_PLF_2, true); - worklist.safe_push (stmt); - break; - } - } - } - } - /* Propagate liveness through arguments of live stmt. */ - while (worklist.length () > 0) - { - ssa_op_iter iter; - use_operand_p use_p; - tree use; - - stmt = worklist.pop (); - FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE) - { - use = USE_FROM_PTR (use_p); - if (TREE_CODE (use) != SSA_NAME) - continue; - stmt1 = SSA_NAME_DEF_STMT (use); - if (gimple_bb (stmt1) != bb || gimple_plf (stmt1, GF_PLF_2)) - continue; - gimple_set_plf (stmt1, GF_PLF_2, true); - worklist.safe_push (stmt1); - } - } - /* Delete dead statements. */ - gsi = gsi_last_bb (bb); - while (!gsi_end_p (gsi)) - { - gimple_stmt_iterator gsiprev = gsi; - gsi_prev (&gsiprev); - stmt = gsi_stmt (gsi); - if (gimple_store_p (stmt)) - { - tree lhs = gimple_get_lhs (stmt); - ao_ref write; - ao_ref_init (&write, lhs); - - if (dse_classify_store (&write, stmt, false, NULL, NULL, latch_vdef) - == DSE_STORE_DEAD) - delete_dead_or_redundant_assignment (&gsi, "dead"); - gsi = gsiprev; - continue; - } - - if (gimple_plf (stmt, GF_PLF_2)) - { - gsi = gsiprev; - continue; - } - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "Delete dead stmt in bb#%d\n", bb->index); - print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); - } - gsi_remove (&gsi, true); - release_defs (stmt); - gsi = gsiprev; - } -} - -/* Return true if VALUE is already available on edge PE. */ - -static bool -ifcvt_available_on_edge_p (edge pe, tree value) -{ - if (is_gimple_min_invariant (value)) - return true; - - if (TREE_CODE (value) == SSA_NAME) - { - basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (value)); - if (!def_bb || dominated_by_p (CDI_DOMINATORS, pe->dest, def_bb)) - return true; - } - - return false; -} - -/* Return true if STMT can be hoisted from if-converted loop LOOP to - edge PE. */ - -static bool -ifcvt_can_hoist (class loop *loop, edge pe, gimple *stmt) -{ - if (auto *call = dyn_cast<gcall *> (stmt)) - { - if (gimple_call_internal_p (call) - && internal_fn_mask_index (gimple_call_internal_fn (call)) >= 0) - return false; - } - else if (auto *assign = dyn_cast<gassign *> (stmt)) - { - if (gimple_assign_rhs_code (assign) == COND_EXPR) - return false; - } - else - return false; - - if (gimple_has_side_effects (stmt) - || gimple_could_trap_p (stmt) - || stmt_could_throw_p (cfun, stmt) - || gimple_vdef (stmt) - || gimple_vuse (stmt)) - return false; - - int num_args = gimple_num_args (stmt); - if (pe != loop_preheader_edge (loop)) - { - for (int i = 0; i < num_args; ++i) - if (!ifcvt_available_on_edge_p (pe, gimple_arg (stmt, i))) - return false; - } - else - { - for (int i = 0; i < num_args; ++i) - if (!expr_invariant_in_loop_p (loop, gimple_arg (stmt, i))) - return false; - } - - return true; -} - -/* Hoist invariant statements from LOOP to edge PE. */ - -static void -ifcvt_hoist_invariants (class loop *loop, edge pe) -{ - gimple_stmt_iterator hoist_gsi = {}; - unsigned int num_blocks = loop->num_nodes; - basic_block *body = get_loop_body (loop); - for (unsigned int i = 0; i < num_blocks; ++i) - for (gimple_stmt_iterator gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi);) - { - gimple *stmt = gsi_stmt (gsi); - if (ifcvt_can_hoist (loop, pe, stmt)) - { - /* Once we've hoisted one statement, insert other statements - after it. */ - gsi_remove (&gsi, false); - if (hoist_gsi.ptr) - gsi_insert_after (&hoist_gsi, stmt, GSI_NEW_STMT); - else - { - gsi_insert_on_edge_immediate (pe, stmt); - hoist_gsi = gsi_for_stmt (stmt); - } - continue; - } - gsi_next (&gsi); - } - free (body); -} - -/* If-convert LOOP when it is legal. For the moment this pass has no - profitability analysis. Returns non-zero todo flags when something - changed. */ - -unsigned int -tree_if_conversion (class loop *loop, vec<gimple *> *preds) -{ - unsigned int todo = 0; - bool aggressive_if_conv; - class loop *rloop; - bitmap exit_bbs; - edge pe; - - again: - rloop = NULL; - ifc_bbs = NULL; - need_to_predicate = false; - need_to_rewrite_undefined = false; - any_complicated_phi = false; - - /* Apply more aggressive if-conversion when loop or its outer loop were - marked with simd pragma. When that's the case, we try to if-convert - loop containing PHIs with more than MAX_PHI_ARG_NUM arguments. */ - aggressive_if_conv = loop->force_vectorize; - if (!aggressive_if_conv) - { - class loop *outer_loop = loop_outer (loop); - if (outer_loop && outer_loop->force_vectorize) - aggressive_if_conv = true; - } - - if (!ifcvt_split_critical_edges (loop, aggressive_if_conv)) - goto cleanup; - - if (!if_convertible_loop_p (loop) - || !dbg_cnt (if_conversion_tree)) - goto cleanup; - - if ((need_to_predicate || any_complicated_phi) - && ((!flag_tree_loop_vectorize && !loop->force_vectorize) - || loop->dont_vectorize)) - goto cleanup; - - /* The edge to insert invariant stmts on. */ - pe = loop_preheader_edge (loop); - - /* Since we have no cost model, always version loops unless the user - specified -ftree-loop-if-convert or unless versioning is required. - Either version this loop, or if the pattern is right for outer-loop - vectorization, version the outer loop. In the latter case we will - still if-convert the original inner loop. */ - if (need_to_predicate - || any_complicated_phi - || flag_tree_loop_if_convert != 1) - { - class loop *vloop - = (versionable_outer_loop_p (loop_outer (loop)) - ? loop_outer (loop) : loop); - class loop *nloop = version_loop_for_if_conversion (vloop, preds); - if (nloop == NULL) - goto cleanup; - if (vloop != loop) - { - /* If versionable_outer_loop_p decided to version the - outer loop, version also the inner loop of the non-vectorized - loop copy. So we transform: - loop1 - loop2 - into: - if (LOOP_VECTORIZED (1, 3)) - { - loop1 - loop2 - } - else - loop3 (copy of loop1) - if (LOOP_VECTORIZED (4, 5)) - loop4 (copy of loop2) - else - loop5 (copy of loop4) */ - gcc_assert (nloop->inner && nloop->inner->next == NULL); - rloop = nloop->inner; - } - else - /* If we versioned loop then make sure to insert invariant - stmts before the .LOOP_VECTORIZED check since the vectorizer - will re-use that for things like runtime alias versioning - whose condition can end up using those invariants. */ - pe = single_pred_edge (gimple_bb (preds->last ())); - } - - /* Now all statements are if-convertible. Combine all the basic - blocks into one huge basic block doing the if-conversion - on-the-fly. */ - combine_blocks (loop); - - /* Perform local CSE, this esp. helps the vectorizer analysis if loads - and stores are involved. CSE only the loop body, not the entry - PHIs, those are to be kept in sync with the non-if-converted copy. - ??? We'll still keep dead stores though. */ - exit_bbs = BITMAP_ALLOC (NULL); - bitmap_set_bit (exit_bbs, single_exit (loop)->dest->index); - bitmap_set_bit (exit_bbs, loop->latch->index); - - std::pair <tree, tree> *name_pair; - unsigned ssa_names_idx; - FOR_EACH_VEC_ELT (redundant_ssa_names, ssa_names_idx, name_pair) - replace_uses_by (name_pair->first, name_pair->second); - redundant_ssa_names.release (); - - todo |= do_rpo_vn (cfun, loop_preheader_edge (loop), exit_bbs); - - /* Delete dead predicate computations. */ - ifcvt_local_dce (loop); - BITMAP_FREE (exit_bbs); - - ifcvt_hoist_invariants (loop, pe); - - todo |= TODO_cleanup_cfg; - - cleanup: - if (ifc_bbs) - { - unsigned int i; - - for (i = 0; i < loop->num_nodes; i++) - free_bb_predicate (ifc_bbs[i]); - - free (ifc_bbs); - ifc_bbs = NULL; - } - if (rloop != NULL) - { - loop = rloop; - goto again; - } - - return todo; -} - -/* Tree if-conversion pass management. */ - -namespace { - -const pass_data pass_data_if_conversion = -{ - GIMPLE_PASS, /* type */ - "ifcvt", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - TV_TREE_LOOP_IFCVT, /* tv_id */ - ( PROP_cfg | PROP_ssa ), /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ -}; - -class pass_if_conversion : public gimple_opt_pass -{ -public: - pass_if_conversion (gcc::context *ctxt) - : gimple_opt_pass (pass_data_if_conversion, ctxt) - {} - - /* opt_pass methods: */ - virtual bool gate (function *); - virtual unsigned int execute (function *); - -}; // class pass_if_conversion - -bool -pass_if_conversion::gate (function *fun) -{ - return (((flag_tree_loop_vectorize || fun->has_force_vectorize_loops) - && flag_tree_loop_if_convert != 0) - || flag_tree_loop_if_convert == 1); -} - -unsigned int -pass_if_conversion::execute (function *fun) -{ - unsigned todo = 0; - - if (number_of_loops (fun) <= 1) - return 0; - - auto_vec<gimple *> preds; - for (auto loop : loops_list (cfun, 0)) - if (flag_tree_loop_if_convert == 1 - || ((flag_tree_loop_vectorize || loop->force_vectorize) - && !loop->dont_vectorize)) - todo |= tree_if_conversion (loop, &preds); - - if (todo) - { - free_numbers_of_iterations_estimates (fun); - scev_reset (); - } - - if (flag_checking) - { - basic_block bb; - FOR_EACH_BB_FN (bb, fun) - gcc_assert (!bb->aux); - } - - /* Perform IL update now, it might elide some loops. */ - if (todo & TODO_cleanup_cfg) - { - cleanup_tree_cfg (); - if (need_ssa_update_p (fun)) - todo |= TODO_update_ssa; - } - if (todo & TODO_update_ssa_any) - update_ssa (todo & TODO_update_ssa_any); - - /* If if-conversion elided the loop fall back to the original one. */ - for (unsigned i = 0; i < preds.length (); ++i) - { - gimple *g = preds[i]; - if (!gimple_bb (g)) - continue; - unsigned ifcvt_loop = tree_to_uhwi (gimple_call_arg (g, 0)); - if (!get_loop (fun, ifcvt_loop)) - { - if (dump_file) - fprintf (dump_file, "If-converted loop vanished\n"); - fold_loop_internal_call (g, boolean_false_node); - } - } - - return 0; -} - -} // anon namespace - -gimple_opt_pass * -make_pass_if_conversion (gcc::context *ctxt) -{ - return new pass_if_conversion (ctxt); -} |