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/lra-constraints.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/lra-constraints.c')
-rw-r--r-- | gcc/lra-constraints.c | 7380 |
1 files changed, 0 insertions, 7380 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c deleted file mode 100644 index 9a333a8..0000000 --- a/gcc/lra-constraints.c +++ /dev/null @@ -1,7380 +0,0 @@ -/* Code for RTL transformations to satisfy insn constraints. - Copyright (C) 2010-2022 Free Software Foundation, Inc. - Contributed by Vladimir Makarov <vmakarov@redhat.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 file contains code for 3 passes: constraint pass, - inheritance/split pass, and pass for undoing failed inheritance and - split. - - The major goal of constraint pass is to transform RTL to satisfy - insn and address constraints by: - o choosing insn alternatives; - o generating *reload insns* (or reloads in brief) and *reload - pseudos* which will get necessary hard registers later; - o substituting pseudos with equivalent values and removing the - instructions that initialized those pseudos. - - The constraint pass has biggest and most complicated code in LRA. - There are a lot of important details like: - o reuse of input reload pseudos to simplify reload pseudo - allocations; - o some heuristics to choose insn alternative to improve the - inheritance; - o early clobbers etc. - - The pass is mimicking former reload pass in alternative choosing - because the reload pass is oriented to current machine description - model. It might be changed if the machine description model is - changed. - - There is special code for preventing all LRA and this pass cycling - in case of bugs. - - On the first iteration of the pass we process every instruction and - choose an alternative for each one. On subsequent iterations we try - to avoid reprocessing instructions if we can be sure that the old - choice is still valid. - - The inheritance/spilt pass is to transform code to achieve - ineheritance and live range splitting. It is done on backward - traversal of EBBs. - - The inheritance optimization goal is to reuse values in hard - registers. There is analogous optimization in old reload pass. The - inheritance is achieved by following transformation: - - reload_p1 <- p reload_p1 <- p - ... new_p <- reload_p1 - ... => ... - reload_p2 <- p reload_p2 <- new_p - - where p is spilled and not changed between the insns. Reload_p1 is - also called *original pseudo* and new_p is called *inheritance - pseudo*. - - The subsequent assignment pass will try to assign the same (or - another if it is not possible) hard register to new_p as to - reload_p1 or reload_p2. - - If the assignment pass fails to assign a hard register to new_p, - this file will undo the inheritance and restore the original code. - This is because implementing the above sequence with a spilled - new_p would make the code much worse. The inheritance is done in - EBB scope. The above is just a simplified example to get an idea - of the inheritance as the inheritance is also done for non-reload - insns. - - Splitting (transformation) is also done in EBB scope on the same - pass as the inheritance: - - r <- ... or ... <- r r <- ... or ... <- r - ... s <- r (new insn -- save) - ... => - ... r <- s (new insn -- restore) - ... <- r ... <- r - - The *split pseudo* s is assigned to the hard register of the - original pseudo or hard register r. - - Splitting is done: - o In EBBs with high register pressure for global pseudos (living - in at least 2 BBs) and assigned to hard registers when there - are more one reloads needing the hard registers; - o for pseudos needing save/restore code around calls. - - If the split pseudo still has the same hard register as the - original pseudo after the subsequent assignment pass or the - original pseudo was split, the opposite transformation is done on - the same pass for undoing inheritance. */ - -#undef REG_OK_STRICT - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "backend.h" -#include "target.h" -#include "rtl.h" -#include "tree.h" -#include "predict.h" -#include "df.h" -#include "memmodel.h" -#include "tm_p.h" -#include "expmed.h" -#include "optabs.h" -#include "regs.h" -#include "ira.h" -#include "recog.h" -#include "output.h" -#include "addresses.h" -#include "expr.h" -#include "cfgrtl.h" -#include "rtl-error.h" -#include "lra.h" -#include "lra-int.h" -#include "print-rtl.h" -#include "function-abi.h" -#include "rtl-iter.h" - -/* Value of LRA_CURR_RELOAD_NUM at the beginning of BB of the current - insn. Remember that LRA_CURR_RELOAD_NUM is the number of emitted - reload insns. */ -static int bb_reload_num; - -/* The current insn being processed and corresponding its single set - (NULL otherwise), its data (basic block, the insn data, the insn - static data, and the mode of each operand). */ -static rtx_insn *curr_insn; -static rtx curr_insn_set; -static basic_block curr_bb; -static lra_insn_recog_data_t curr_id; -static struct lra_static_insn_data *curr_static_id; -static machine_mode curr_operand_mode[MAX_RECOG_OPERANDS]; -/* Mode of the register substituted by its equivalence with VOIDmode - (e.g. constant) and whose subreg is given operand of the current - insn. VOIDmode in all other cases. */ -static machine_mode original_subreg_reg_mode[MAX_RECOG_OPERANDS]; - - - -/* Start numbers for new registers and insns at the current constraints - pass start. */ -static int new_regno_start; -static int new_insn_uid_start; - -/* If LOC is nonnull, strip any outer subreg from it. */ -static inline rtx * -strip_subreg (rtx *loc) -{ - return loc && GET_CODE (*loc) == SUBREG ? &SUBREG_REG (*loc) : loc; -} - -/* Return hard regno of REGNO or if it is was not assigned to a hard - register, use a hard register from its allocno class. */ -static int -get_try_hard_regno (int regno) -{ - int hard_regno; - enum reg_class rclass; - - if ((hard_regno = regno) >= FIRST_PSEUDO_REGISTER) - hard_regno = lra_get_regno_hard_regno (regno); - if (hard_regno >= 0) - return hard_regno; - rclass = lra_get_allocno_class (regno); - if (rclass == NO_REGS) - return -1; - return ira_class_hard_regs[rclass][0]; -} - -/* Return the hard regno of X after removing its subreg. If X is not - a register or a subreg of a register, return -1. If X is a pseudo, - use its assignment. If FINAL_P return the final hard regno which will - be after elimination. */ -static int -get_hard_regno (rtx x, bool final_p) -{ - rtx reg; - int hard_regno; - - reg = x; - if (SUBREG_P (x)) - reg = SUBREG_REG (x); - if (! REG_P (reg)) - return -1; - if (! HARD_REGISTER_NUM_P (hard_regno = REGNO (reg))) - hard_regno = lra_get_regno_hard_regno (hard_regno); - if (hard_regno < 0) - return -1; - if (final_p) - hard_regno = lra_get_elimination_hard_regno (hard_regno); - if (SUBREG_P (x)) - hard_regno += subreg_regno_offset (hard_regno, GET_MODE (reg), - SUBREG_BYTE (x), GET_MODE (x)); - return hard_regno; -} - -/* If REGNO is a hard register or has been allocated a hard register, - return the class of that register. If REGNO is a reload pseudo - created by the current constraints pass, return its allocno class. - Return NO_REGS otherwise. */ -static enum reg_class -get_reg_class (int regno) -{ - int hard_regno; - - if (! HARD_REGISTER_NUM_P (hard_regno = regno)) - hard_regno = lra_get_regno_hard_regno (regno); - if (hard_regno >= 0) - { - hard_regno = lra_get_elimination_hard_regno (hard_regno); - return REGNO_REG_CLASS (hard_regno); - } - if (regno >= new_regno_start) - return lra_get_allocno_class (regno); - return NO_REGS; -} - -/* Return true if REG satisfies (or will satisfy) reg class constraint - CL. Use elimination first if REG is a hard register. If REG is a - reload pseudo created by this constraints pass, assume that it will - be allocated a hard register from its allocno class, but allow that - class to be narrowed to CL if it is currently a superset of CL and - if either: - - - ALLOW_ALL_RELOAD_CLASS_CHANGES_P is true or - - the instruction we're processing is not a reload move. - - If NEW_CLASS is nonnull, set *NEW_CLASS to the new allocno class of - REGNO (reg), or NO_REGS if no change in its class was needed. */ -static bool -in_class_p (rtx reg, enum reg_class cl, enum reg_class *new_class, - bool allow_all_reload_class_changes_p = false) -{ - enum reg_class rclass, common_class; - machine_mode reg_mode; - rtx src; - int class_size, hard_regno, nregs, i, j; - int regno = REGNO (reg); - - if (new_class != NULL) - *new_class = NO_REGS; - if (regno < FIRST_PSEUDO_REGISTER) - { - rtx final_reg = reg; - rtx *final_loc = &final_reg; - - lra_eliminate_reg_if_possible (final_loc); - return TEST_HARD_REG_BIT (reg_class_contents[cl], REGNO (*final_loc)); - } - reg_mode = GET_MODE (reg); - rclass = get_reg_class (regno); - src = curr_insn_set != NULL ? SET_SRC (curr_insn_set) : NULL; - if (regno < new_regno_start - /* Do not allow the constraints for reload instructions to - influence the classes of new pseudos. These reloads are - typically moves that have many alternatives, and restricting - reload pseudos for one alternative may lead to situations - where other reload pseudos are no longer allocatable. */ - || (!allow_all_reload_class_changes_p - && INSN_UID (curr_insn) >= new_insn_uid_start - && src != NULL - && ((REG_P (src) || MEM_P (src)) - || (GET_CODE (src) == SUBREG - && (REG_P (SUBREG_REG (src)) || MEM_P (SUBREG_REG (src))))))) - /* When we don't know what class will be used finally for reload - pseudos, we use ALL_REGS. */ - return ((regno >= new_regno_start && rclass == ALL_REGS) - || (rclass != NO_REGS && ira_class_subset_p[rclass][cl] - && ! hard_reg_set_subset_p (reg_class_contents[cl], - lra_no_alloc_regs))); - else - { - common_class = ira_reg_class_subset[rclass][cl]; - if (new_class != NULL) - *new_class = common_class; - if (hard_reg_set_subset_p (reg_class_contents[common_class], - lra_no_alloc_regs)) - return false; - /* Check that there are enough allocatable regs. */ - class_size = ira_class_hard_regs_num[common_class]; - for (i = 0; i < class_size; i++) - { - hard_regno = ira_class_hard_regs[common_class][i]; - nregs = hard_regno_nregs (hard_regno, reg_mode); - if (nregs == 1) - return true; - for (j = 0; j < nregs; j++) - if (TEST_HARD_REG_BIT (lra_no_alloc_regs, hard_regno + j) - || ! TEST_HARD_REG_BIT (reg_class_contents[common_class], - hard_regno + j)) - break; - if (j >= nregs) - return true; - } - return false; - } -} - -/* Return true if REGNO satisfies a memory constraint. */ -static bool -in_mem_p (int regno) -{ - return get_reg_class (regno) == NO_REGS; -} - -/* Return 1 if ADDR is a valid memory address for mode MODE in address - space AS, and check that each pseudo has the proper kind of hard - reg. */ -static int -valid_address_p (machine_mode mode ATTRIBUTE_UNUSED, - rtx addr, addr_space_t as) -{ -#ifdef GO_IF_LEGITIMATE_ADDRESS - lra_assert (ADDR_SPACE_GENERIC_P (as)); - GO_IF_LEGITIMATE_ADDRESS (mode, addr, win); - return 0; - - win: - return 1; -#else - return targetm.addr_space.legitimate_address_p (mode, addr, 0, as); -#endif -} - -namespace { - /* Temporarily eliminates registers in an address (for the lifetime of - the object). */ - class address_eliminator { - public: - address_eliminator (struct address_info *ad); - ~address_eliminator (); - - private: - struct address_info *m_ad; - rtx *m_base_loc; - rtx m_base_reg; - rtx *m_index_loc; - rtx m_index_reg; - }; -} - -address_eliminator::address_eliminator (struct address_info *ad) - : m_ad (ad), - m_base_loc (strip_subreg (ad->base_term)), - m_base_reg (NULL_RTX), - m_index_loc (strip_subreg (ad->index_term)), - m_index_reg (NULL_RTX) -{ - if (m_base_loc != NULL) - { - m_base_reg = *m_base_loc; - /* If we have non-legitimate address which is decomposed not in - the way we expected, don't do elimination here. In such case - the address will be reloaded and elimination will be done in - reload insn finally. */ - if (REG_P (m_base_reg)) - lra_eliminate_reg_if_possible (m_base_loc); - if (m_ad->base_term2 != NULL) - *m_ad->base_term2 = *m_ad->base_term; - } - if (m_index_loc != NULL) - { - m_index_reg = *m_index_loc; - if (REG_P (m_index_reg)) - lra_eliminate_reg_if_possible (m_index_loc); - } -} - -address_eliminator::~address_eliminator () -{ - if (m_base_loc && *m_base_loc != m_base_reg) - { - *m_base_loc = m_base_reg; - if (m_ad->base_term2 != NULL) - *m_ad->base_term2 = *m_ad->base_term; - } - if (m_index_loc && *m_index_loc != m_index_reg) - *m_index_loc = m_index_reg; -} - -/* Return true if the eliminated form of AD is a legitimate target address. - If OP is a MEM, AD is the address within OP, otherwise OP should be - ignored. CONSTRAINT is one constraint that the operand may need - to meet. */ -static bool -valid_address_p (rtx op, struct address_info *ad, - enum constraint_num constraint) -{ - address_eliminator eliminator (ad); - - /* Allow a memory OP if it matches CONSTRAINT, even if CONSTRAINT is more - forgiving than "m". - Need to extract memory from op for special memory constraint, - i.e. bcst_mem_operand in i386 backend. */ - if (MEM_P (extract_mem_from_operand (op)) - && insn_extra_relaxed_memory_constraint (constraint) - && constraint_satisfied_p (op, constraint)) - return true; - - return valid_address_p (ad->mode, *ad->outer, ad->as); -} - -/* For special_memory_operand, it could be false for MEM_P (op), - i.e. bcst_mem_operand in i386 backend. - Extract and return real memory operand or op. */ -rtx -extract_mem_from_operand (rtx op) -{ - for (rtx x = op;; x = XEXP (x, 0)) - { - if (MEM_P (x)) - return x; - if (GET_RTX_LENGTH (GET_CODE (x)) != 1 - || GET_RTX_FORMAT (GET_CODE (x))[0] != 'e') - break; - } - return op; -} - -/* Return true if the eliminated form of memory reference OP satisfies - extra (special) memory constraint CONSTRAINT. */ -static bool -satisfies_memory_constraint_p (rtx op, enum constraint_num constraint) -{ - struct address_info ad; - rtx mem = extract_mem_from_operand (op); - if (!MEM_P (mem)) - return false; - - decompose_mem_address (&ad, mem); - address_eliminator eliminator (&ad); - return constraint_satisfied_p (op, constraint); -} - -/* Return true if the eliminated form of address AD satisfies extra - address constraint CONSTRAINT. */ -static bool -satisfies_address_constraint_p (struct address_info *ad, - enum constraint_num constraint) -{ - address_eliminator eliminator (ad); - return constraint_satisfied_p (*ad->outer, constraint); -} - -/* Return true if the eliminated form of address OP satisfies extra - address constraint CONSTRAINT. */ -static bool -satisfies_address_constraint_p (rtx op, enum constraint_num constraint) -{ - struct address_info ad; - - decompose_lea_address (&ad, &op); - return satisfies_address_constraint_p (&ad, constraint); -} - -/* Initiate equivalences for LRA. As we keep original equivalences - before any elimination, we need to make copies otherwise any change - in insns might change the equivalences. */ -void -lra_init_equiv (void) -{ - ira_expand_reg_equiv (); - for (int i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++) - { - rtx res; - - if ((res = ira_reg_equiv[i].memory) != NULL_RTX) - ira_reg_equiv[i].memory = copy_rtx (res); - if ((res = ira_reg_equiv[i].invariant) != NULL_RTX) - ira_reg_equiv[i].invariant = copy_rtx (res); - } -} - -static rtx loc_equivalence_callback (rtx, const_rtx, void *); - -/* Update equivalence for REGNO. We need to this as the equivalence - might contain other pseudos which are changed by their - equivalences. */ -static void -update_equiv (int regno) -{ - rtx x; - - if ((x = ira_reg_equiv[regno].memory) != NULL_RTX) - ira_reg_equiv[regno].memory - = simplify_replace_fn_rtx (x, NULL_RTX, loc_equivalence_callback, - NULL_RTX); - if ((x = ira_reg_equiv[regno].invariant) != NULL_RTX) - ira_reg_equiv[regno].invariant - = simplify_replace_fn_rtx (x, NULL_RTX, loc_equivalence_callback, - NULL_RTX); -} - -/* If we have decided to substitute X with another value, return that - value, otherwise return X. */ -static rtx -get_equiv (rtx x) -{ - int regno; - rtx res; - - if (! REG_P (x) || (regno = REGNO (x)) < FIRST_PSEUDO_REGISTER - || ! ira_reg_equiv[regno].defined_p - || ! ira_reg_equiv[regno].profitable_p - || lra_get_regno_hard_regno (regno) >= 0) - return x; - if ((res = ira_reg_equiv[regno].memory) != NULL_RTX) - { - if (targetm.cannot_substitute_mem_equiv_p (res)) - return x; - return res; - } - if ((res = ira_reg_equiv[regno].constant) != NULL_RTX) - return res; - if ((res = ira_reg_equiv[regno].invariant) != NULL_RTX) - return res; - gcc_unreachable (); -} - -/* If we have decided to substitute X with the equivalent value, - return that value after elimination for INSN, otherwise return - X. */ -static rtx -get_equiv_with_elimination (rtx x, rtx_insn *insn) -{ - rtx res = get_equiv (x); - - if (x == res || CONSTANT_P (res)) - return res; - return lra_eliminate_regs_1 (insn, res, GET_MODE (res), - false, false, 0, true); -} - -/* Set up curr_operand_mode. */ -static void -init_curr_operand_mode (void) -{ - int nop = curr_static_id->n_operands; - for (int i = 0; i < nop; i++) - { - machine_mode mode = GET_MODE (*curr_id->operand_loc[i]); - if (mode == VOIDmode) - { - /* The .md mode for address operands is the mode of the - addressed value rather than the mode of the address itself. */ - if (curr_id->icode >= 0 && curr_static_id->operand[i].is_address) - mode = Pmode; - else - mode = curr_static_id->operand[i].mode; - } - curr_operand_mode[i] = mode; - } -} - - - -/* The page contains code to reuse input reloads. */ - -/* Structure describes input reload of the current insns. */ -struct input_reload -{ - /* True for input reload of matched operands. */ - bool match_p; - /* Reloaded value. */ - rtx input; - /* Reload pseudo used. */ - rtx reg; -}; - -/* The number of elements in the following array. */ -static int curr_insn_input_reloads_num; -/* Array containing info about input reloads. It is used to find the - same input reload and reuse the reload pseudo in this case. */ -static struct input_reload curr_insn_input_reloads[LRA_MAX_INSN_RELOADS]; - -/* Initiate data concerning reuse of input reloads for the current - insn. */ -static void -init_curr_insn_input_reloads (void) -{ - curr_insn_input_reloads_num = 0; -} - -/* The canonical form of an rtx inside a MEM is not necessarily the same as the - canonical form of the rtx outside the MEM. Fix this up in the case that - we're reloading an address (and therefore pulling it outside a MEM). */ -static rtx -canonicalize_reload_addr (rtx addr) -{ - subrtx_var_iterator::array_type array; - FOR_EACH_SUBRTX_VAR (iter, array, addr, NONCONST) - { - rtx x = *iter; - if (GET_CODE (x) == MULT && CONST_INT_P (XEXP (x, 1))) - { - const HOST_WIDE_INT ci = INTVAL (XEXP (x, 1)); - const int pwr2 = exact_log2 (ci); - if (pwr2 > 0) - { - /* Rewrite this to use a shift instead, which is canonical when - outside of a MEM. */ - PUT_CODE (x, ASHIFT); - XEXP (x, 1) = GEN_INT (pwr2); - } - } - } - - return addr; -} - -/* Create a new pseudo using MODE, RCLASS, ORIGINAL or reuse an existing - reload pseudo. Don't reuse an existing reload pseudo if IN_SUBREG_P - is true and the reused pseudo should be wrapped up in a SUBREG. - The result pseudo is returned through RESULT_REG. Return TRUE if we - created a new pseudo, FALSE if we reused an existing reload pseudo. - Use TITLE to describe new registers for debug purposes. */ -static bool -get_reload_reg (enum op_type type, machine_mode mode, rtx original, - enum reg_class rclass, bool in_subreg_p, - const char *title, rtx *result_reg) -{ - int i, regno; - enum reg_class new_class; - bool unique_p = false; - - if (type == OP_OUT) - { - /* Output reload registers tend to start out with a conservative - choice of register class. Usually this is ALL_REGS, although - a target might narrow it (for performance reasons) through - targetm.preferred_reload_class. It's therefore quite common - for a reload instruction to require a more restrictive class - than the class that was originally assigned to the reload register. - - In these situations, it's more efficient to refine the choice - of register class rather than create a second reload register. - This also helps to avoid cycling for registers that are only - used by reload instructions. */ - if (REG_P (original) - && (int) REGNO (original) >= new_regno_start - && INSN_UID (curr_insn) >= new_insn_uid_start - && in_class_p (original, rclass, &new_class, true)) - { - unsigned int regno = REGNO (original); - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, " Reuse r%d for output ", regno); - dump_value_slim (lra_dump_file, original, 1); - } - if (new_class != lra_get_allocno_class (regno)) - lra_change_class (regno, new_class, ", change to", false); - if (lra_dump_file != NULL) - fprintf (lra_dump_file, "\n"); - *result_reg = original; - return false; - } - *result_reg - = lra_create_new_reg_with_unique_value (mode, original, rclass, title); - return true; - } - /* Prevent reuse value of expression with side effects, - e.g. volatile memory. */ - if (! side_effects_p (original)) - for (i = 0; i < curr_insn_input_reloads_num; i++) - { - if (! curr_insn_input_reloads[i].match_p - && rtx_equal_p (curr_insn_input_reloads[i].input, original) - && in_class_p (curr_insn_input_reloads[i].reg, rclass, &new_class)) - { - rtx reg = curr_insn_input_reloads[i].reg; - regno = REGNO (reg); - /* If input is equal to original and both are VOIDmode, - GET_MODE (reg) might be still different from mode. - Ensure we don't return *result_reg with wrong mode. */ - if (GET_MODE (reg) != mode) - { - if (in_subreg_p) - continue; - if (maybe_lt (GET_MODE_SIZE (GET_MODE (reg)), - GET_MODE_SIZE (mode))) - continue; - reg = lowpart_subreg (mode, reg, GET_MODE (reg)); - if (reg == NULL_RTX || GET_CODE (reg) != SUBREG) - continue; - } - *result_reg = reg; - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, " Reuse r%d for reload ", regno); - dump_value_slim (lra_dump_file, original, 1); - } - if (new_class != lra_get_allocno_class (regno)) - lra_change_class (regno, new_class, ", change to", false); - if (lra_dump_file != NULL) - fprintf (lra_dump_file, "\n"); - return false; - } - /* If we have an input reload with a different mode, make sure it - will get a different hard reg. */ - else if (REG_P (original) - && REG_P (curr_insn_input_reloads[i].input) - && REGNO (original) == REGNO (curr_insn_input_reloads[i].input) - && (GET_MODE (original) - != GET_MODE (curr_insn_input_reloads[i].input))) - unique_p = true; - } - *result_reg = (unique_p - ? lra_create_new_reg_with_unique_value - : lra_create_new_reg) (mode, original, rclass, title); - lra_assert (curr_insn_input_reloads_num < LRA_MAX_INSN_RELOADS); - curr_insn_input_reloads[curr_insn_input_reloads_num].input = original; - curr_insn_input_reloads[curr_insn_input_reloads_num].match_p = false; - curr_insn_input_reloads[curr_insn_input_reloads_num++].reg = *result_reg; - return true; -} - - -/* The page contains major code to choose the current insn alternative - and generate reloads for it. */ - -/* Return the offset from REGNO of the least significant register - in (reg:MODE REGNO). - - This function is used to tell whether two registers satisfy - a matching constraint. (reg:MODE1 REGNO1) matches (reg:MODE2 REGNO2) if: - - REGNO1 + lra_constraint_offset (REGNO1, MODE1) - == REGNO2 + lra_constraint_offset (REGNO2, MODE2) */ -int -lra_constraint_offset (int regno, machine_mode mode) -{ - lra_assert (regno < FIRST_PSEUDO_REGISTER); - - scalar_int_mode int_mode; - if (WORDS_BIG_ENDIAN - && is_a <scalar_int_mode> (mode, &int_mode) - && GET_MODE_SIZE (int_mode) > UNITS_PER_WORD) - return hard_regno_nregs (regno, mode) - 1; - return 0; -} - -/* Like rtx_equal_p except that it allows a REG and a SUBREG to match - if they are the same hard reg, and has special hacks for - auto-increment and auto-decrement. This is specifically intended for - process_alt_operands to use in determining whether two operands - match. X is the operand whose number is the lower of the two. - - It is supposed that X is the output operand and Y is the input - operand. Y_HARD_REGNO is the final hard regno of register Y or - register in subreg Y as we know it now. Otherwise, it is a - negative value. */ -static bool -operands_match_p (rtx x, rtx y, int y_hard_regno) -{ - int i; - RTX_CODE code = GET_CODE (x); - const char *fmt; - - if (x == y) - return true; - if ((code == REG || (code == SUBREG && REG_P (SUBREG_REG (x)))) - && (REG_P (y) || (GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y))))) - { - int j; - - i = get_hard_regno (x, false); - if (i < 0) - goto slow; - - if ((j = y_hard_regno) < 0) - goto slow; - - i += lra_constraint_offset (i, GET_MODE (x)); - j += lra_constraint_offset (j, GET_MODE (y)); - - return i == j; - } - - /* If two operands must match, because they are really a single - operand of an assembler insn, then two post-increments are invalid - because the assembler insn would increment only once. On the - other hand, a post-increment matches ordinary indexing if the - post-increment is the output operand. */ - if (code == POST_DEC || code == POST_INC || code == POST_MODIFY) - return operands_match_p (XEXP (x, 0), y, y_hard_regno); - - /* Two pre-increments are invalid because the assembler insn would - increment only once. On the other hand, a pre-increment matches - ordinary indexing if the pre-increment is the input operand. */ - if (GET_CODE (y) == PRE_DEC || GET_CODE (y) == PRE_INC - || GET_CODE (y) == PRE_MODIFY) - return operands_match_p (x, XEXP (y, 0), -1); - - slow: - - if (code == REG && REG_P (y)) - return REGNO (x) == REGNO (y); - - if (code == REG && GET_CODE (y) == SUBREG && REG_P (SUBREG_REG (y)) - && x == SUBREG_REG (y)) - return true; - if (GET_CODE (y) == REG && code == SUBREG && REG_P (SUBREG_REG (x)) - && SUBREG_REG (x) == y) - return true; - - /* Now we have disposed of all the cases in which different rtx - codes can match. */ - if (code != GET_CODE (y)) - return false; - - /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */ - if (GET_MODE (x) != GET_MODE (y)) - return false; - - switch (code) - { - CASE_CONST_UNIQUE: - return false; - - case CONST_VECTOR: - if (!same_vector_encodings_p (x, y)) - return false; - break; - - case LABEL_REF: - return label_ref_label (x) == label_ref_label (y); - case SYMBOL_REF: - return XSTR (x, 0) == XSTR (y, 0); - - default: - break; - } - - /* Compare the elements. If any pair of corresponding elements fail - to match, return false for the whole things. */ - - fmt = GET_RTX_FORMAT (code); - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - int val, j; - switch (fmt[i]) - { - case 'w': - if (XWINT (x, i) != XWINT (y, i)) - return false; - break; - - case 'i': - if (XINT (x, i) != XINT (y, i)) - return false; - break; - - case 'p': - if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y))) - return false; - break; - - case 'e': - val = operands_match_p (XEXP (x, i), XEXP (y, i), -1); - if (val == 0) - return false; - break; - - case '0': - break; - - case 'E': - if (XVECLEN (x, i) != XVECLEN (y, i)) - return false; - for (j = XVECLEN (x, i) - 1; j >= 0; --j) - { - val = operands_match_p (XVECEXP (x, i, j), XVECEXP (y, i, j), -1); - if (val == 0) - return false; - } - break; - - /* It is believed that rtx's at this level will never - contain anything but integers and other rtx's, except for - within LABEL_REFs and SYMBOL_REFs. */ - default: - gcc_unreachable (); - } - } - return true; -} - -/* True if X is a constant that can be forced into the constant pool. - MODE is the mode of the operand, or VOIDmode if not known. */ -#define CONST_POOL_OK_P(MODE, X) \ - ((MODE) != VOIDmode \ - && CONSTANT_P (X) \ - && GET_CODE (X) != HIGH \ - && GET_MODE_SIZE (MODE).is_constant () \ - && !targetm.cannot_force_const_mem (MODE, X)) - -/* True if C is a non-empty register class that has too few registers - to be safely used as a reload target class. */ -#define SMALL_REGISTER_CLASS_P(C) \ - (ira_class_hard_regs_num [(C)] == 1 \ - || (ira_class_hard_regs_num [(C)] >= 1 \ - && targetm.class_likely_spilled_p (C))) - -/* If REG is a reload pseudo, try to make its class satisfying CL. */ -static void -narrow_reload_pseudo_class (rtx reg, enum reg_class cl) -{ - enum reg_class rclass; - - /* Do not make more accurate class from reloads generated. They are - mostly moves with a lot of constraints. Making more accurate - class may results in very narrow class and impossibility of find - registers for several reloads of one insn. */ - if (INSN_UID (curr_insn) >= new_insn_uid_start) - return; - if (GET_CODE (reg) == SUBREG) - reg = SUBREG_REG (reg); - if (! REG_P (reg) || (int) REGNO (reg) < new_regno_start) - return; - if (in_class_p (reg, cl, &rclass) && rclass != cl) - lra_change_class (REGNO (reg), rclass, " Change to", true); -} - -/* Searches X for any reference to a reg with the same value as REGNO, - returning the rtx of the reference found if any. Otherwise, - returns NULL_RTX. */ -static rtx -regno_val_use_in (unsigned int regno, rtx x) -{ - const char *fmt; - int i, j; - rtx tem; - - if (REG_P (x) && lra_reg_info[REGNO (x)].val == lra_reg_info[regno].val) - return x; - - fmt = GET_RTX_FORMAT (GET_CODE (x)); - for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - { - if ((tem = regno_val_use_in (regno, XEXP (x, i)))) - return tem; - } - else if (fmt[i] == 'E') - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - if ((tem = regno_val_use_in (regno , XVECEXP (x, i, j)))) - return tem; - } - - return NULL_RTX; -} - -/* Return true if all current insn non-output operands except INS (it - has a negaitve end marker) do not use pseudos with the same value - as REGNO. */ -static bool -check_conflict_input_operands (int regno, signed char *ins) -{ - int in; - int n_operands = curr_static_id->n_operands; - - for (int nop = 0; nop < n_operands; nop++) - if (! curr_static_id->operand[nop].is_operator - && curr_static_id->operand[nop].type != OP_OUT) - { - for (int i = 0; (in = ins[i]) >= 0; i++) - if (in == nop) - break; - if (in < 0 - && regno_val_use_in (regno, *curr_id->operand_loc[nop]) != NULL_RTX) - return false; - } - return true; -} - -/* Generate reloads for matching OUT and INS (array of input operand - numbers with end marker -1) with reg class GOAL_CLASS, considering - output operands OUTS (similar array to INS) needing to be in different - registers. Add input and output reloads correspondingly to the lists - *BEFORE and *AFTER. OUT might be negative. In this case we generate - input reloads for matched input operands INS. EARLY_CLOBBER_P is a flag - that the output operand is early clobbered for chosen alternative. */ -static void -match_reload (signed char out, signed char *ins, signed char *outs, - enum reg_class goal_class, rtx_insn **before, - rtx_insn **after, bool early_clobber_p) -{ - bool out_conflict; - int i, in; - rtx new_in_reg, new_out_reg, reg; - machine_mode inmode, outmode; - rtx in_rtx = *curr_id->operand_loc[ins[0]]; - rtx out_rtx = out < 0 ? in_rtx : *curr_id->operand_loc[out]; - - inmode = curr_operand_mode[ins[0]]; - outmode = out < 0 ? inmode : curr_operand_mode[out]; - push_to_sequence (*before); - if (inmode != outmode) - { - /* process_alt_operands has already checked that the mode sizes - are ordered. */ - if (partial_subreg_p (outmode, inmode)) - { - reg = new_in_reg - = lra_create_new_reg_with_unique_value (inmode, in_rtx, - goal_class, ""); - new_out_reg = gen_lowpart_SUBREG (outmode, reg); - LRA_SUBREG_P (new_out_reg) = 1; - /* If the input reg is dying here, we can use the same hard - register for REG and IN_RTX. We do it only for original - pseudos as reload pseudos can die although original - pseudos still live where reload pseudos dies. */ - if (REG_P (in_rtx) && (int) REGNO (in_rtx) < lra_new_regno_start - && find_regno_note (curr_insn, REG_DEAD, REGNO (in_rtx)) - && (!early_clobber_p - || check_conflict_input_operands(REGNO (in_rtx), ins))) - lra_assign_reg_val (REGNO (in_rtx), REGNO (reg)); - } - else - { - reg = new_out_reg - = lra_create_new_reg_with_unique_value (outmode, out_rtx, - goal_class, ""); - new_in_reg = gen_lowpart_SUBREG (inmode, reg); - /* NEW_IN_REG is non-paradoxical subreg. We don't want - NEW_OUT_REG living above. We add clobber clause for - this. This is just a temporary clobber. We can remove - it at the end of LRA work. */ - rtx_insn *clobber = emit_clobber (new_out_reg); - LRA_TEMP_CLOBBER_P (PATTERN (clobber)) = 1; - LRA_SUBREG_P (new_in_reg) = 1; - if (GET_CODE (in_rtx) == SUBREG) - { - rtx subreg_reg = SUBREG_REG (in_rtx); - - /* If SUBREG_REG is dying here and sub-registers IN_RTX - and NEW_IN_REG are similar, we can use the same hard - register for REG and SUBREG_REG. */ - if (REG_P (subreg_reg) - && (int) REGNO (subreg_reg) < lra_new_regno_start - && GET_MODE (subreg_reg) == outmode - && known_eq (SUBREG_BYTE (in_rtx), SUBREG_BYTE (new_in_reg)) - && find_regno_note (curr_insn, REG_DEAD, REGNO (subreg_reg)) - && (! early_clobber_p - || check_conflict_input_operands (REGNO (subreg_reg), - ins))) - lra_assign_reg_val (REGNO (subreg_reg), REGNO (reg)); - } - } - } - else - { - /* Pseudos have values -- see comments for lra_reg_info. - Different pseudos with the same value do not conflict even if - they live in the same place. When we create a pseudo we - assign value of original pseudo (if any) from which we - created the new pseudo. If we create the pseudo from the - input pseudo, the new pseudo will have no conflict with the - input pseudo which is wrong when the input pseudo lives after - the insn and as the new pseudo value is changed by the insn - output. Therefore we create the new pseudo from the output - except the case when we have single matched dying input - pseudo. - - We cannot reuse the current output register because we might - have a situation like "a <- a op b", where the constraints - force the second input operand ("b") to match the output - operand ("a"). "b" must then be copied into a new register - so that it doesn't clobber the current value of "a". - - We cannot use the same value if the output pseudo is - early clobbered or the input pseudo is mentioned in the - output, e.g. as an address part in memory, because - output reload will actually extend the pseudo liveness. - We don't care about eliminable hard regs here as we are - interesting only in pseudos. */ - - /* Matching input's register value is the same as one of the other - output operand. Output operands in a parallel insn must be in - different registers. */ - out_conflict = false; - if (REG_P (in_rtx)) - { - for (i = 0; outs[i] >= 0; i++) - { - rtx other_out_rtx = *curr_id->operand_loc[outs[i]]; - if (outs[i] != out && REG_P (other_out_rtx) - && (regno_val_use_in (REGNO (in_rtx), other_out_rtx) - != NULL_RTX)) - { - out_conflict = true; - break; - } - } - } - - new_in_reg = new_out_reg - = (! early_clobber_p && ins[1] < 0 && REG_P (in_rtx) - && (int) REGNO (in_rtx) < lra_new_regno_start - && find_regno_note (curr_insn, REG_DEAD, REGNO (in_rtx)) - && (! early_clobber_p - || check_conflict_input_operands (REGNO (in_rtx), ins)) - && (out < 0 - || regno_val_use_in (REGNO (in_rtx), out_rtx) == NULL_RTX) - && !out_conflict - ? lra_create_new_reg (inmode, in_rtx, goal_class, "") - : lra_create_new_reg_with_unique_value (outmode, out_rtx, - goal_class, "")); - } - /* In operand can be got from transformations before processing insn - constraints. One example of such transformations is subreg - reloading (see function simplify_operand_subreg). The new - pseudos created by the transformations might have inaccurate - class (ALL_REGS) and we should make their classes more - accurate. */ - narrow_reload_pseudo_class (in_rtx, goal_class); - lra_emit_move (copy_rtx (new_in_reg), in_rtx); - *before = get_insns (); - end_sequence (); - /* Add the new pseudo to consider values of subsequent input reload - pseudos. */ - lra_assert (curr_insn_input_reloads_num < LRA_MAX_INSN_RELOADS); - curr_insn_input_reloads[curr_insn_input_reloads_num].input = in_rtx; - curr_insn_input_reloads[curr_insn_input_reloads_num].match_p = true; - curr_insn_input_reloads[curr_insn_input_reloads_num++].reg = new_in_reg; - for (i = 0; (in = ins[i]) >= 0; i++) - if (GET_MODE (*curr_id->operand_loc[in]) == VOIDmode - || GET_MODE (new_in_reg) == GET_MODE (*curr_id->operand_loc[in])) - *curr_id->operand_loc[in] = new_in_reg; - else - { - lra_assert - (GET_MODE (new_out_reg) == GET_MODE (*curr_id->operand_loc[in])); - *curr_id->operand_loc[in] = new_out_reg; - } - lra_update_dups (curr_id, ins); - if (out < 0) - return; - /* See a comment for the input operand above. */ - narrow_reload_pseudo_class (out_rtx, goal_class); - if (find_reg_note (curr_insn, REG_UNUSED, out_rtx) == NULL_RTX) - { - reg = SUBREG_P (out_rtx) ? SUBREG_REG (out_rtx) : out_rtx; - start_sequence (); - /* If we had strict_low_part, use it also in reload to keep other - parts unchanged but do it only for regs as strict_low_part - has no sense for memory and probably there is no insn pattern - to match the reload insn in memory case. */ - if (out >= 0 && curr_static_id->operand[out].strict_low && REG_P (reg)) - out_rtx = gen_rtx_STRICT_LOW_PART (VOIDmode, out_rtx); - lra_emit_move (out_rtx, copy_rtx (new_out_reg)); - emit_insn (*after); - *after = get_insns (); - end_sequence (); - } - *curr_id->operand_loc[out] = new_out_reg; - lra_update_dup (curr_id, out); -} - -/* Return register class which is union of all reg classes in insn - constraint alternative string starting with P. */ -static enum reg_class -reg_class_from_constraints (const char *p) -{ - int c, len; - enum reg_class op_class = NO_REGS; - - do - switch ((c = *p, len = CONSTRAINT_LEN (c, p)), c) - { - case '#': - case ',': - return op_class; - - case 'g': - op_class = reg_class_subunion[op_class][GENERAL_REGS]; - break; - - default: - enum constraint_num cn = lookup_constraint (p); - enum reg_class cl = reg_class_for_constraint (cn); - if (cl == NO_REGS) - { - if (insn_extra_address_constraint (cn)) - op_class - = (reg_class_subunion - [op_class][base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, - ADDRESS, SCRATCH)]); - break; - } - - op_class = reg_class_subunion[op_class][cl]; - break; - } - while ((p += len), c); - return op_class; -} - -/* If OP is a register, return the class of the register as per - get_reg_class, otherwise return NO_REGS. */ -static inline enum reg_class -get_op_class (rtx op) -{ - return REG_P (op) ? get_reg_class (REGNO (op)) : NO_REGS; -} - -/* Return generated insn mem_pseudo:=val if TO_P or val:=mem_pseudo - otherwise. If modes of MEM_PSEUDO and VAL are different, use - SUBREG for VAL to make them equal. */ -static rtx_insn * -emit_spill_move (bool to_p, rtx mem_pseudo, rtx val) -{ - if (GET_MODE (mem_pseudo) != GET_MODE (val)) - { - /* Usually size of mem_pseudo is greater than val size but in - rare cases it can be less as it can be defined by target - dependent macro HARD_REGNO_CALLER_SAVE_MODE. */ - if (! MEM_P (val)) - { - val = gen_lowpart_SUBREG (GET_MODE (mem_pseudo), - GET_CODE (val) == SUBREG - ? SUBREG_REG (val) : val); - LRA_SUBREG_P (val) = 1; - } - else - { - mem_pseudo = gen_lowpart_SUBREG (GET_MODE (val), mem_pseudo); - LRA_SUBREG_P (mem_pseudo) = 1; - } - } - return to_p ? gen_move_insn (mem_pseudo, val) - : gen_move_insn (val, mem_pseudo); -} - -/* Process a special case insn (register move), return true if we - don't need to process it anymore. INSN should be a single set - insn. Set up that RTL was changed through CHANGE_P and that hook - TARGET_SECONDARY_MEMORY_NEEDED says to use secondary memory through - SEC_MEM_P. */ -static bool -check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED) -{ - int sregno, dregno; - rtx dest, src, dreg, sreg, new_reg, scratch_reg; - rtx_insn *before; - enum reg_class dclass, sclass, secondary_class; - secondary_reload_info sri; - - lra_assert (curr_insn_set != NULL_RTX); - dreg = dest = SET_DEST (curr_insn_set); - sreg = src = SET_SRC (curr_insn_set); - if (GET_CODE (dest) == SUBREG) - dreg = SUBREG_REG (dest); - if (GET_CODE (src) == SUBREG) - sreg = SUBREG_REG (src); - if (! (REG_P (dreg) || MEM_P (dreg)) || ! (REG_P (sreg) || MEM_P (sreg))) - return false; - sclass = dclass = NO_REGS; - if (REG_P (dreg)) - dclass = get_reg_class (REGNO (dreg)); - gcc_assert (dclass < LIM_REG_CLASSES && dclass >= NO_REGS); - if (dclass == ALL_REGS) - /* ALL_REGS is used for new pseudos created by transformations - like reload of SUBREG_REG (see function - simplify_operand_subreg). We don't know their class yet. We - should figure out the class from processing the insn - constraints not in this fast path function. Even if ALL_REGS - were a right class for the pseudo, secondary_... hooks usually - are not define for ALL_REGS. */ - return false; - if (REG_P (sreg)) - sclass = get_reg_class (REGNO (sreg)); - gcc_assert (sclass < LIM_REG_CLASSES && sclass >= NO_REGS); - if (sclass == ALL_REGS) - /* See comments above. */ - return false; - if (sclass == NO_REGS && dclass == NO_REGS) - return false; - if (targetm.secondary_memory_needed (GET_MODE (src), sclass, dclass) - && ((sclass != NO_REGS && dclass != NO_REGS) - || (GET_MODE (src) - != targetm.secondary_memory_needed_mode (GET_MODE (src))))) - { - *sec_mem_p = true; - return false; - } - if (! REG_P (dreg) || ! REG_P (sreg)) - return false; - sri.prev_sri = NULL; - sri.icode = CODE_FOR_nothing; - sri.extra_cost = 0; - secondary_class = NO_REGS; - /* Set up hard register for a reload pseudo for hook - secondary_reload because some targets just ignore unassigned - pseudos in the hook. */ - if (dclass != NO_REGS && lra_get_regno_hard_regno (REGNO (dreg)) < 0) - { - dregno = REGNO (dreg); - reg_renumber[dregno] = ira_class_hard_regs[dclass][0]; - } - else - dregno = -1; - if (sclass != NO_REGS && lra_get_regno_hard_regno (REGNO (sreg)) < 0) - { - sregno = REGNO (sreg); - reg_renumber[sregno] = ira_class_hard_regs[sclass][0]; - } - else - sregno = -1; - if (sclass != NO_REGS) - secondary_class - = (enum reg_class) targetm.secondary_reload (false, dest, - (reg_class_t) sclass, - GET_MODE (src), &sri); - if (sclass == NO_REGS - || ((secondary_class != NO_REGS || sri.icode != CODE_FOR_nothing) - && dclass != NO_REGS)) - { - enum reg_class old_sclass = secondary_class; - secondary_reload_info old_sri = sri; - - sri.prev_sri = NULL; - sri.icode = CODE_FOR_nothing; - sri.extra_cost = 0; - secondary_class - = (enum reg_class) targetm.secondary_reload (true, src, - (reg_class_t) dclass, - GET_MODE (src), &sri); - /* Check the target hook consistency. */ - lra_assert - ((secondary_class == NO_REGS && sri.icode == CODE_FOR_nothing) - || (old_sclass == NO_REGS && old_sri.icode == CODE_FOR_nothing) - || (secondary_class == old_sclass && sri.icode == old_sri.icode)); - } - if (sregno >= 0) - reg_renumber [sregno] = -1; - if (dregno >= 0) - reg_renumber [dregno] = -1; - if (secondary_class == NO_REGS && sri.icode == CODE_FOR_nothing) - return false; - *change_p = true; - new_reg = NULL_RTX; - if (secondary_class != NO_REGS) - new_reg = lra_create_new_reg_with_unique_value (GET_MODE (src), NULL_RTX, - secondary_class, - "secondary"); - start_sequence (); - if (sri.icode == CODE_FOR_nothing) - lra_emit_move (new_reg, src); - else - { - enum reg_class scratch_class; - - scratch_class = (reg_class_from_constraints - (insn_data[sri.icode].operand[2].constraint)); - scratch_reg = (lra_create_new_reg_with_unique_value - (insn_data[sri.icode].operand[2].mode, NULL_RTX, - scratch_class, "scratch")); - emit_insn (GEN_FCN (sri.icode) (new_reg != NULL_RTX ? new_reg : dest, - src, scratch_reg)); - } - before = get_insns (); - end_sequence (); - lra_process_new_insns (curr_insn, before, NULL, "Inserting the move"); - if (new_reg != NULL_RTX) - SET_SRC (curr_insn_set) = new_reg; - else - { - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, "Deleting move %u\n", INSN_UID (curr_insn)); - dump_insn_slim (lra_dump_file, curr_insn); - } - lra_set_insn_deleted (curr_insn); - return true; - } - return false; -} - -/* The following data describe the result of process_alt_operands. - The data are used in curr_insn_transform to generate reloads. */ - -/* The chosen reg classes which should be used for the corresponding - operands. */ -static enum reg_class goal_alt[MAX_RECOG_OPERANDS]; -/* True if the operand should be the same as another operand and that - other operand does not need a reload. */ -static bool goal_alt_match_win[MAX_RECOG_OPERANDS]; -/* True if the operand does not need a reload. */ -static bool goal_alt_win[MAX_RECOG_OPERANDS]; -/* True if the operand can be offsetable memory. */ -static bool goal_alt_offmemok[MAX_RECOG_OPERANDS]; -/* The number of an operand to which given operand can be matched to. */ -static int goal_alt_matches[MAX_RECOG_OPERANDS]; -/* The number of elements in the following array. */ -static int goal_alt_dont_inherit_ops_num; -/* Numbers of operands whose reload pseudos should not be inherited. */ -static int goal_alt_dont_inherit_ops[MAX_RECOG_OPERANDS]; -/* True if the insn commutative operands should be swapped. */ -static bool goal_alt_swapped; -/* The chosen insn alternative. */ -static int goal_alt_number; - -/* True if the corresponding operand is the result of an equivalence - substitution. */ -static bool equiv_substition_p[MAX_RECOG_OPERANDS]; - -/* The following five variables are used to choose the best insn - alternative. They reflect final characteristics of the best - alternative. */ - -/* Number of necessary reloads and overall cost reflecting the - previous value and other unpleasantness of the best alternative. */ -static int best_losers, best_overall; -/* Overall number hard registers used for reloads. For example, on - some targets we need 2 general registers to reload DFmode and only - one floating point register. */ -static int best_reload_nregs; -/* Overall number reflecting distances of previous reloading the same - value. The distances are counted from the current BB start. It is - used to improve inheritance chances. */ -static int best_reload_sum; - -/* True if the current insn should have no correspondingly input or - output reloads. */ -static bool no_input_reloads_p, no_output_reloads_p; - -/* True if we swapped the commutative operands in the current - insn. */ -static int curr_swapped; - -/* if CHECK_ONLY_P is false, arrange for address element *LOC to be a - register of class CL. Add any input reloads to list BEFORE. AFTER - is nonnull if *LOC is an automodified value; handle that case by - adding the required output reloads to list AFTER. Return true if - the RTL was changed. - - if CHECK_ONLY_P is true, check that the *LOC is a correct address - register. Return false if the address register is correct. */ -static bool -process_addr_reg (rtx *loc, bool check_only_p, rtx_insn **before, rtx_insn **after, - enum reg_class cl) -{ - int regno; - enum reg_class rclass, new_class; - rtx reg; - rtx new_reg; - machine_mode mode; - bool subreg_p, before_p = false; - - subreg_p = GET_CODE (*loc) == SUBREG; - if (subreg_p) - { - reg = SUBREG_REG (*loc); - mode = GET_MODE (reg); - - /* For mode with size bigger than ptr_mode, there unlikely to be "mov" - between two registers with different classes, but there normally will - be "mov" which transfers element of vector register into the general - register, and this normally will be a subreg which should be reloaded - as a whole. This is particularly likely to be triggered when - -fno-split-wide-types specified. */ - if (!REG_P (reg) - || in_class_p (reg, cl, &new_class) - || known_le (GET_MODE_SIZE (mode), GET_MODE_SIZE (ptr_mode))) - loc = &SUBREG_REG (*loc); - } - - reg = *loc; - mode = GET_MODE (reg); - if (! REG_P (reg)) - { - if (check_only_p) - return true; - /* Always reload memory in an address even if the target supports - such addresses. */ - new_reg = lra_create_new_reg_with_unique_value (mode, reg, cl, "address"); - before_p = true; - } - else - { - regno = REGNO (reg); - rclass = get_reg_class (regno); - if (! check_only_p - && (*loc = get_equiv_with_elimination (reg, curr_insn)) != reg) - { - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, - "Changing pseudo %d in address of insn %u on equiv ", - REGNO (reg), INSN_UID (curr_insn)); - dump_value_slim (lra_dump_file, *loc, 1); - fprintf (lra_dump_file, "\n"); - } - *loc = copy_rtx (*loc); - } - if (*loc != reg || ! in_class_p (reg, cl, &new_class)) - { - if (check_only_p) - return true; - reg = *loc; - if (get_reload_reg (after == NULL ? OP_IN : OP_INOUT, - mode, reg, cl, subreg_p, "address", &new_reg)) - before_p = true; - } - else if (new_class != NO_REGS && rclass != new_class) - { - if (check_only_p) - return true; - lra_change_class (regno, new_class, " Change to", true); - return false; - } - else - return false; - } - if (before_p) - { - push_to_sequence (*before); - lra_emit_move (new_reg, reg); - *before = get_insns (); - end_sequence (); - } - *loc = new_reg; - if (after != NULL) - { - start_sequence (); - lra_emit_move (before_p ? copy_rtx (reg) : reg, new_reg); - emit_insn (*after); - *after = get_insns (); - end_sequence (); - } - return true; -} - -/* Insert move insn in simplify_operand_subreg. BEFORE returns - the insn to be inserted before curr insn. AFTER returns the - the insn to be inserted after curr insn. ORIGREG and NEWREG - are the original reg and new reg for reload. */ -static void -insert_move_for_subreg (rtx_insn **before, rtx_insn **after, rtx origreg, - rtx newreg) -{ - if (before) - { - push_to_sequence (*before); - lra_emit_move (newreg, origreg); - *before = get_insns (); - end_sequence (); - } - if (after) - { - start_sequence (); - lra_emit_move (origreg, newreg); - emit_insn (*after); - *after = get_insns (); - end_sequence (); - } -} - -static int valid_address_p (machine_mode mode, rtx addr, addr_space_t as); -static bool process_address (int, bool, rtx_insn **, rtx_insn **); - -/* Make reloads for subreg in operand NOP with internal subreg mode - REG_MODE, add new reloads for further processing. Return true if - any change was done. */ -static bool -simplify_operand_subreg (int nop, machine_mode reg_mode) -{ - int hard_regno, inner_hard_regno; - rtx_insn *before, *after; - machine_mode mode, innermode; - rtx reg, new_reg; - rtx operand = *curr_id->operand_loc[nop]; - enum reg_class regclass; - enum op_type type; - - before = after = NULL; - - if (GET_CODE (operand) != SUBREG) - return false; - - mode = GET_MODE (operand); - reg = SUBREG_REG (operand); - innermode = GET_MODE (reg); - type = curr_static_id->operand[nop].type; - if (MEM_P (reg)) - { - const bool addr_was_valid - = valid_address_p (innermode, XEXP (reg, 0), MEM_ADDR_SPACE (reg)); - alter_subreg (curr_id->operand_loc[nop], false); - rtx subst = *curr_id->operand_loc[nop]; - lra_assert (MEM_P (subst)); - const bool addr_is_valid = valid_address_p (GET_MODE (subst), - XEXP (subst, 0), - MEM_ADDR_SPACE (subst)); - if (!addr_was_valid - || addr_is_valid - || ((get_constraint_type (lookup_constraint - (curr_static_id->operand[nop].constraint)) - != CT_SPECIAL_MEMORY) - /* We still can reload address and if the address is - valid, we can remove subreg without reloading its - inner memory. */ - && valid_address_p (GET_MODE (subst), - regno_reg_rtx - [ira_class_hard_regs - [base_reg_class (GET_MODE (subst), - MEM_ADDR_SPACE (subst), - ADDRESS, SCRATCH)][0]], - MEM_ADDR_SPACE (subst)))) - { - /* If we change the address for a paradoxical subreg of memory, the - new address might violate the necessary alignment or the access - might be slow; take this into consideration. We need not worry - about accesses beyond allocated memory for paradoxical memory - subregs as we don't substitute such equiv memory (see processing - equivalences in function lra_constraints) and because for spilled - pseudos we allocate stack memory enough for the biggest - corresponding paradoxical subreg. - - However, do not blindly simplify a (subreg (mem ...)) for - WORD_REGISTER_OPERATIONS targets as this may lead to loading junk - data into a register when the inner is narrower than outer or - missing important data from memory when the inner is wider than - outer. This rule only applies to modes that are no wider than - a word. - - If valid memory becomes invalid after subreg elimination - and address might be different we still have to reload - memory. - */ - if ((! addr_was_valid - || addr_is_valid - || known_eq (GET_MODE_SIZE (mode), GET_MODE_SIZE (innermode))) - && !(maybe_ne (GET_MODE_PRECISION (mode), - GET_MODE_PRECISION (innermode)) - && known_le (GET_MODE_SIZE (mode), UNITS_PER_WORD) - && known_le (GET_MODE_SIZE (innermode), UNITS_PER_WORD) - && WORD_REGISTER_OPERATIONS) - && (!(MEM_ALIGN (subst) < GET_MODE_ALIGNMENT (mode) - && targetm.slow_unaligned_access (mode, MEM_ALIGN (subst))) - || (MEM_ALIGN (reg) < GET_MODE_ALIGNMENT (innermode) - && targetm.slow_unaligned_access (innermode, - MEM_ALIGN (reg))))) - return true; - - *curr_id->operand_loc[nop] = operand; - - /* But if the address was not valid, we cannot reload the MEM without - reloading the address first. */ - if (!addr_was_valid) - process_address (nop, false, &before, &after); - - /* INNERMODE is fast, MODE slow. Reload the mem in INNERMODE. */ - enum reg_class rclass - = (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS); - if (get_reload_reg (curr_static_id->operand[nop].type, innermode, - reg, rclass, TRUE, "slow/invalid mem", &new_reg)) - { - bool insert_before, insert_after; - bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg)); - - insert_before = (type != OP_OUT - || partial_subreg_p (mode, innermode)); - insert_after = type != OP_IN; - insert_move_for_subreg (insert_before ? &before : NULL, - insert_after ? &after : NULL, - reg, new_reg); - } - SUBREG_REG (operand) = new_reg; - - /* Convert to MODE. */ - reg = operand; - rclass - = (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS); - if (get_reload_reg (curr_static_id->operand[nop].type, mode, reg, - rclass, TRUE, "slow/invalid mem", &new_reg)) - { - bool insert_before, insert_after; - bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg)); - - insert_before = type != OP_OUT; - insert_after = type != OP_IN; - insert_move_for_subreg (insert_before ? &before : NULL, - insert_after ? &after : NULL, - reg, new_reg); - } - *curr_id->operand_loc[nop] = new_reg; - lra_process_new_insns (curr_insn, before, after, - "Inserting slow/invalid mem reload"); - return true; - } - - /* If the address was valid and became invalid, prefer to reload - the memory. Typical case is when the index scale should - correspond the memory. */ - *curr_id->operand_loc[nop] = operand; - /* Do not return false here as the MEM_P (reg) will be processed - later in this function. */ - } - else if (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER) - { - alter_subreg (curr_id->operand_loc[nop], false); - return true; - } - else if (CONSTANT_P (reg)) - { - /* Try to simplify subreg of constant. It is usually result of - equivalence substitution. */ - if (innermode == VOIDmode - && (innermode = original_subreg_reg_mode[nop]) == VOIDmode) - innermode = curr_static_id->operand[nop].mode; - if ((new_reg = simplify_subreg (mode, reg, innermode, - SUBREG_BYTE (operand))) != NULL_RTX) - { - *curr_id->operand_loc[nop] = new_reg; - return true; - } - } - /* Put constant into memory when we have mixed modes. It generates - a better code in most cases as it does not need a secondary - reload memory. It also prevents LRA looping when LRA is using - secondary reload memory again and again. */ - if (CONSTANT_P (reg) && CONST_POOL_OK_P (reg_mode, reg) - && SCALAR_INT_MODE_P (reg_mode) != SCALAR_INT_MODE_P (mode)) - { - SUBREG_REG (operand) = force_const_mem (reg_mode, reg); - alter_subreg (curr_id->operand_loc[nop], false); - return true; - } - /* Force a reload of the SUBREG_REG if this is a constant or PLUS or - if there may be a problem accessing OPERAND in the outer - mode. */ - if ((REG_P (reg) - && REGNO (reg) >= FIRST_PSEUDO_REGISTER - && (hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0 - /* Don't reload paradoxical subregs because we could be looping - having repeatedly final regno out of hard regs range. */ - && (hard_regno_nregs (hard_regno, innermode) - >= hard_regno_nregs (hard_regno, mode)) - && simplify_subreg_regno (hard_regno, innermode, - SUBREG_BYTE (operand), mode) < 0 - /* Don't reload subreg for matching reload. It is actually - valid subreg in LRA. */ - && ! LRA_SUBREG_P (operand)) - || CONSTANT_P (reg) || GET_CODE (reg) == PLUS || MEM_P (reg)) - { - enum reg_class rclass; - - if (REG_P (reg)) - /* There is a big probability that we will get the same class - for the new pseudo and we will get the same insn which - means infinite looping. So spill the new pseudo. */ - rclass = NO_REGS; - else - /* The class will be defined later in curr_insn_transform. */ - rclass - = (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS); - - if (get_reload_reg (curr_static_id->operand[nop].type, reg_mode, reg, - rclass, TRUE, "subreg reg", &new_reg)) - { - bool insert_before, insert_after; - bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg)); - - insert_before = (type != OP_OUT - || read_modify_subreg_p (operand)); - insert_after = (type != OP_IN); - insert_move_for_subreg (insert_before ? &before : NULL, - insert_after ? &after : NULL, - reg, new_reg); - } - SUBREG_REG (operand) = new_reg; - lra_process_new_insns (curr_insn, before, after, - "Inserting subreg reload"); - return true; - } - /* Force a reload for a paradoxical subreg. For paradoxical subreg, - IRA allocates hardreg to the inner pseudo reg according to its mode - instead of the outermode, so the size of the hardreg may not be enough - to contain the outermode operand, in that case we may need to insert - reload for the reg. For the following two types of paradoxical subreg, - we need to insert reload: - 1. If the op_type is OP_IN, and the hardreg could not be paired with - other hardreg to contain the outermode operand - (checked by in_hard_reg_set_p), we need to insert the reload. - 2. If the op_type is OP_OUT or OP_INOUT. - - Here is a paradoxical subreg example showing how the reload is generated: - - (insn 5 4 7 2 (set (reg:TI 106 [ __comp ]) - (subreg:TI (reg:DI 107 [ __comp ]) 0)) {*movti_internal_rex64} - - In IRA, reg107 is allocated to a DImode hardreg. We use x86-64 as example - here, if reg107 is assigned to hardreg R15, because R15 is the last - hardreg, compiler cannot find another hardreg to pair with R15 to - contain TImode data. So we insert a TImode reload reg180 for it. - After reload is inserted: - - (insn 283 0 0 (set (subreg:DI (reg:TI 180 [orig:107 __comp ] [107]) 0) - (reg:DI 107 [ __comp ])) -1 - (insn 5 4 7 2 (set (reg:TI 106 [ __comp ]) - (subreg:TI (reg:TI 180 [orig:107 __comp ] [107]) 0)) {*movti_internal_rex64} - - Two reload hard registers will be allocated to reg180 to save TImode data - in LRA_assign. - - For LRA pseudos this should normally be handled by the biggest_mode - mechanism. However, it's possible for new uses of an LRA pseudo - to be introduced after we've allocated it, such as when undoing - inheritance, and the allocated register might not then be appropriate - for the new uses. */ - else if (REG_P (reg) - && REGNO (reg) >= FIRST_PSEUDO_REGISTER - && paradoxical_subreg_p (operand) - && (inner_hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0 - && ((hard_regno - = simplify_subreg_regno (inner_hard_regno, innermode, - SUBREG_BYTE (operand), mode)) < 0 - || ((hard_regno_nregs (inner_hard_regno, innermode) - < hard_regno_nregs (hard_regno, mode)) - && (regclass = lra_get_allocno_class (REGNO (reg))) - && (type != OP_IN - || !in_hard_reg_set_p (reg_class_contents[regclass], - mode, hard_regno) - || overlaps_hard_reg_set_p (lra_no_alloc_regs, - mode, hard_regno))))) - { - /* The class will be defined later in curr_insn_transform. */ - enum reg_class rclass - = (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS); - - if (get_reload_reg (curr_static_id->operand[nop].type, mode, reg, - rclass, TRUE, "paradoxical subreg", &new_reg)) - { - rtx subreg; - bool insert_before, insert_after; - - PUT_MODE (new_reg, mode); - subreg = gen_lowpart_SUBREG (innermode, new_reg); - bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg)); - - insert_before = (type != OP_OUT); - insert_after = (type != OP_IN); - insert_move_for_subreg (insert_before ? &before : NULL, - insert_after ? &after : NULL, - reg, subreg); - } - SUBREG_REG (operand) = new_reg; - lra_process_new_insns (curr_insn, before, after, - "Inserting paradoxical subreg reload"); - return true; - } - return false; -} - -/* Return TRUE if X refers for a hard register from SET. */ -static bool -uses_hard_regs_p (rtx x, HARD_REG_SET set) -{ - int i, j, x_hard_regno; - machine_mode mode; - const char *fmt; - enum rtx_code code; - - if (x == NULL_RTX) - return false; - code = GET_CODE (x); - mode = GET_MODE (x); - - if (code == SUBREG) - { - /* For all SUBREGs we want to check whether the full multi-register - overlaps the set. For normal SUBREGs this means 'get_hard_regno' of - the inner register, for paradoxical SUBREGs this means the - 'get_hard_regno' of the full SUBREG and for complete SUBREGs either is - fine. Use the wider mode for all cases. */ - rtx subreg = SUBREG_REG (x); - mode = wider_subreg_mode (x); - if (mode == GET_MODE (subreg)) - { - x = subreg; - code = GET_CODE (x); - } - } - - if (REG_P (x) || SUBREG_P (x)) - { - x_hard_regno = get_hard_regno (x, true); - return (x_hard_regno >= 0 - && overlaps_hard_reg_set_p (set, mode, x_hard_regno)); - } - fmt = GET_RTX_FORMAT (code); - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - { - if (uses_hard_regs_p (XEXP (x, i), set)) - return true; - } - else if (fmt[i] == 'E') - { - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - if (uses_hard_regs_p (XVECEXP (x, i, j), set)) - return true; - } - } - return false; -} - -/* Return true if OP is a spilled pseudo. */ -static inline bool -spilled_pseudo_p (rtx op) -{ - return (REG_P (op) - && REGNO (op) >= FIRST_PSEUDO_REGISTER && in_mem_p (REGNO (op))); -} - -/* Return true if X is a general constant. */ -static inline bool -general_constant_p (rtx x) -{ - return CONSTANT_P (x) && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (x)); -} - -static bool -reg_in_class_p (rtx reg, enum reg_class cl) -{ - if (cl == NO_REGS) - return get_reg_class (REGNO (reg)) == NO_REGS; - return in_class_p (reg, cl, NULL); -} - -/* Return true if SET of RCLASS contains no hard regs which can be - used in MODE. */ -static bool -prohibited_class_reg_set_mode_p (enum reg_class rclass, - HARD_REG_SET &set, - machine_mode mode) -{ - HARD_REG_SET temp; - - lra_assert (hard_reg_set_subset_p (reg_class_contents[rclass], set)); - temp = set & ~lra_no_alloc_regs; - return (hard_reg_set_subset_p - (temp, ira_prohibited_class_mode_regs[rclass][mode])); -} - - -/* Used to check validity info about small class input operands. It - should be incremented at start of processing an insn - alternative. */ -static unsigned int curr_small_class_check = 0; - -/* Update number of used inputs of class OP_CLASS for operand NOP - of alternative NALT. Return true if we have more such class operands - than the number of available regs. */ -static bool -update_and_check_small_class_inputs (int nop, int nalt, - enum reg_class op_class) -{ - static unsigned int small_class_check[LIM_REG_CLASSES]; - static int small_class_input_nums[LIM_REG_CLASSES]; - - if (SMALL_REGISTER_CLASS_P (op_class) - /* We are interesting in classes became small because of fixing - some hard regs, e.g. by an user through GCC options. */ - && hard_reg_set_intersect_p (reg_class_contents[op_class], - ira_no_alloc_regs) - && (curr_static_id->operand[nop].type != OP_OUT - || TEST_BIT (curr_static_id->operand[nop].early_clobber_alts, nalt))) - { - if (small_class_check[op_class] == curr_small_class_check) - small_class_input_nums[op_class]++; - else - { - small_class_check[op_class] = curr_small_class_check; - small_class_input_nums[op_class] = 1; - } - if (small_class_input_nums[op_class] > ira_class_hard_regs_num[op_class]) - return true; - } - return false; -} - -/* Major function to choose the current insn alternative and what - operands should be reloaded and how. If ONLY_ALTERNATIVE is not - negative we should consider only this alternative. Return false if - we cannot choose the alternative or find how to reload the - operands. */ -static bool -process_alt_operands (int only_alternative) -{ - bool ok_p = false; - int nop, overall, nalt; - int n_alternatives = curr_static_id->n_alternatives; - int n_operands = curr_static_id->n_operands; - /* LOSERS counts the operands that don't fit this alternative and - would require loading. */ - int losers; - int addr_losers; - /* REJECT is a count of how undesirable this alternative says it is - if any reloading is required. If the alternative matches exactly - then REJECT is ignored, but otherwise it gets this much counted - against it in addition to the reloading needed. */ - int reject; - /* This is defined by '!' or '?' alternative constraint and added to - reject. But in some cases it can be ignored. */ - int static_reject; - int op_reject; - /* The number of elements in the following array. */ - int early_clobbered_regs_num; - /* Numbers of operands which are early clobber registers. */ - int early_clobbered_nops[MAX_RECOG_OPERANDS]; - enum reg_class curr_alt[MAX_RECOG_OPERANDS]; - HARD_REG_SET curr_alt_set[MAX_RECOG_OPERANDS]; - bool curr_alt_match_win[MAX_RECOG_OPERANDS]; - bool curr_alt_win[MAX_RECOG_OPERANDS]; - bool curr_alt_offmemok[MAX_RECOG_OPERANDS]; - int curr_alt_matches[MAX_RECOG_OPERANDS]; - /* The number of elements in the following array. */ - int curr_alt_dont_inherit_ops_num; - /* Numbers of operands whose reload pseudos should not be inherited. */ - int curr_alt_dont_inherit_ops[MAX_RECOG_OPERANDS]; - rtx op; - /* The register when the operand is a subreg of register, otherwise the - operand itself. */ - rtx no_subreg_reg_operand[MAX_RECOG_OPERANDS]; - /* The register if the operand is a register or subreg of register, - otherwise NULL. */ - rtx operand_reg[MAX_RECOG_OPERANDS]; - int hard_regno[MAX_RECOG_OPERANDS]; - machine_mode biggest_mode[MAX_RECOG_OPERANDS]; - int reload_nregs, reload_sum; - bool costly_p; - enum reg_class cl; - - /* Calculate some data common for all alternatives to speed up the - function. */ - for (nop = 0; nop < n_operands; nop++) - { - rtx reg; - - op = no_subreg_reg_operand[nop] = *curr_id->operand_loc[nop]; - /* The real hard regno of the operand after the allocation. */ - hard_regno[nop] = get_hard_regno (op, true); - - operand_reg[nop] = reg = op; - biggest_mode[nop] = GET_MODE (op); - if (GET_CODE (op) == SUBREG) - { - biggest_mode[nop] = wider_subreg_mode (op); - operand_reg[nop] = reg = SUBREG_REG (op); - } - if (! REG_P (reg)) - operand_reg[nop] = NULL_RTX; - else if (REGNO (reg) >= FIRST_PSEUDO_REGISTER - || ((int) REGNO (reg) - == lra_get_elimination_hard_regno (REGNO (reg)))) - no_subreg_reg_operand[nop] = reg; - else - operand_reg[nop] = no_subreg_reg_operand[nop] - /* Just use natural mode for elimination result. It should - be enough for extra constraints hooks. */ - = regno_reg_rtx[hard_regno[nop]]; - } - - /* The constraints are made of several alternatives. Each operand's - constraint looks like foo,bar,... with commas separating the - alternatives. The first alternatives for all operands go - together, the second alternatives go together, etc. - - First loop over alternatives. */ - alternative_mask preferred = curr_id->preferred_alternatives; - if (only_alternative >= 0) - preferred &= ALTERNATIVE_BIT (only_alternative); - - for (nalt = 0; nalt < n_alternatives; nalt++) - { - /* Loop over operands for one constraint alternative. */ - if (!TEST_BIT (preferred, nalt)) - continue; - - bool matching_early_clobber[MAX_RECOG_OPERANDS]; - curr_small_class_check++; - overall = losers = addr_losers = 0; - static_reject = reject = reload_nregs = reload_sum = 0; - for (nop = 0; nop < n_operands; nop++) - { - int inc = (curr_static_id - ->operand_alternative[nalt * n_operands + nop].reject); - if (lra_dump_file != NULL && inc != 0) - fprintf (lra_dump_file, - " Staticly defined alt reject+=%d\n", inc); - static_reject += inc; - matching_early_clobber[nop] = 0; - } - reject += static_reject; - early_clobbered_regs_num = 0; - - for (nop = 0; nop < n_operands; nop++) - { - const char *p; - char *end; - int len, c, m, i, opalt_num, this_alternative_matches; - bool win, did_match, offmemok, early_clobber_p; - /* false => this operand can be reloaded somehow for this - alternative. */ - bool badop; - /* true => this operand can be reloaded if the alternative - allows regs. */ - bool winreg; - /* True if a constant forced into memory would be OK for - this operand. */ - bool constmemok; - enum reg_class this_alternative, this_costly_alternative; - HARD_REG_SET this_alternative_set, this_costly_alternative_set; - bool this_alternative_match_win, this_alternative_win; - bool this_alternative_offmemok; - bool scratch_p; - machine_mode mode; - enum constraint_num cn; - - opalt_num = nalt * n_operands + nop; - if (curr_static_id->operand_alternative[opalt_num].anything_ok) - { - /* Fast track for no constraints at all. */ - curr_alt[nop] = NO_REGS; - CLEAR_HARD_REG_SET (curr_alt_set[nop]); - curr_alt_win[nop] = true; - curr_alt_match_win[nop] = false; - curr_alt_offmemok[nop] = false; - curr_alt_matches[nop] = -1; - continue; - } - - op = no_subreg_reg_operand[nop]; - mode = curr_operand_mode[nop]; - - win = did_match = winreg = offmemok = constmemok = false; - badop = true; - - early_clobber_p = false; - p = curr_static_id->operand_alternative[opalt_num].constraint; - - this_costly_alternative = this_alternative = NO_REGS; - /* We update set of possible hard regs besides its class - because reg class might be inaccurate. For example, - union of LO_REGS (l), HI_REGS(h), and STACK_REG(k) in ARM - is translated in HI_REGS because classes are merged by - pairs and there is no accurate intermediate class. */ - CLEAR_HARD_REG_SET (this_alternative_set); - CLEAR_HARD_REG_SET (this_costly_alternative_set); - this_alternative_win = false; - this_alternative_match_win = false; - this_alternative_offmemok = false; - this_alternative_matches = -1; - - /* An empty constraint should be excluded by the fast - track. */ - lra_assert (*p != 0 && *p != ','); - - op_reject = 0; - /* Scan this alternative's specs for this operand; set WIN - if the operand fits any letter in this alternative. - Otherwise, clear BADOP if this operand could fit some - letter after reloads, or set WINREG if this operand could - fit after reloads provided the constraint allows some - registers. */ - costly_p = false; - do - { - switch ((c = *p, len = CONSTRAINT_LEN (c, p)), c) - { - case '\0': - len = 0; - break; - case ',': - c = '\0'; - break; - - case '&': - early_clobber_p = true; - break; - - case '$': - op_reject += LRA_MAX_REJECT; - break; - case '^': - op_reject += LRA_LOSER_COST_FACTOR; - break; - - case '#': - /* Ignore rest of this alternative. */ - c = '\0'; - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - int m_hregno; - bool match_p; - - m = strtoul (p, &end, 10); - p = end; - len = 0; - lra_assert (nop > m); - - /* Reject matches if we don't know which operand is - bigger. This situation would arguably be a bug in - an .md pattern, but could also occur in a user asm. */ - if (!ordered_p (GET_MODE_SIZE (biggest_mode[m]), - GET_MODE_SIZE (biggest_mode[nop]))) - break; - - /* Don't match wrong asm insn operands for proper - diagnostic later. */ - if (INSN_CODE (curr_insn) < 0 - && (curr_operand_mode[m] == BLKmode - || curr_operand_mode[nop] == BLKmode) - && curr_operand_mode[m] != curr_operand_mode[nop]) - break; - - m_hregno = get_hard_regno (*curr_id->operand_loc[m], false); - /* We are supposed to match a previous operand. - If we do, we win if that one did. If we do - not, count both of the operands as losers. - (This is too conservative, since most of the - time only a single reload insn will be needed - to make the two operands win. As a result, - this alternative may be rejected when it is - actually desirable.) */ - match_p = false; - if (operands_match_p (*curr_id->operand_loc[nop], - *curr_id->operand_loc[m], m_hregno)) - { - /* We should reject matching of an early - clobber operand if the matching operand is - not dying in the insn. */ - if (!TEST_BIT (curr_static_id->operand[m] - .early_clobber_alts, nalt) - || operand_reg[nop] == NULL_RTX - || (find_regno_note (curr_insn, REG_DEAD, - REGNO (op)) - || REGNO (op) == REGNO (operand_reg[m]))) - match_p = true; - } - if (match_p) - { - /* If we are matching a non-offsettable - address where an offsettable address was - expected, then we must reject this - combination, because we can't reload - it. */ - if (curr_alt_offmemok[m] - && MEM_P (*curr_id->operand_loc[m]) - && curr_alt[m] == NO_REGS && ! curr_alt_win[m]) - continue; - } - else - { - /* If the operands do not match and one - operand is INOUT, we can not match them. - Try other possibilities, e.g. other - alternatives or commutative operand - exchange. */ - if (curr_static_id->operand[nop].type == OP_INOUT - || curr_static_id->operand[m].type == OP_INOUT) - break; - /* Operands don't match. If the operands are - different user defined explicit hard - registers, then we cannot make them match - when one is early clobber operand. */ - if ((REG_P (*curr_id->operand_loc[nop]) - || SUBREG_P (*curr_id->operand_loc[nop])) - && (REG_P (*curr_id->operand_loc[m]) - || SUBREG_P (*curr_id->operand_loc[m]))) - { - rtx nop_reg = *curr_id->operand_loc[nop]; - if (SUBREG_P (nop_reg)) - nop_reg = SUBREG_REG (nop_reg); - rtx m_reg = *curr_id->operand_loc[m]; - if (SUBREG_P (m_reg)) - m_reg = SUBREG_REG (m_reg); - - if (REG_P (nop_reg) - && HARD_REGISTER_P (nop_reg) - && REG_USERVAR_P (nop_reg) - && REG_P (m_reg) - && HARD_REGISTER_P (m_reg) - && REG_USERVAR_P (m_reg)) - { - int i; - - for (i = 0; i < early_clobbered_regs_num; i++) - if (m == early_clobbered_nops[i]) - break; - if (i < early_clobbered_regs_num - || early_clobber_p) - break; - } - } - /* Both operands must allow a reload register, - otherwise we cannot make them match. */ - if (curr_alt[m] == NO_REGS) - break; - /* Retroactively mark the operand we had to - match as a loser, if it wasn't already and - it wasn't matched to a register constraint - (e.g it might be matched by memory). */ - if (curr_alt_win[m] - && (operand_reg[m] == NULL_RTX - || hard_regno[m] < 0)) - { - losers++; - reload_nregs - += (ira_reg_class_max_nregs[curr_alt[m]] - [GET_MODE (*curr_id->operand_loc[m])]); - } - - /* Prefer matching earlyclobber alternative as - it results in less hard regs required for - the insn than a non-matching earlyclobber - alternative. */ - if (TEST_BIT (curr_static_id->operand[m] - .early_clobber_alts, nalt)) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Matching earlyclobber alt:" - " reject--\n", - nop); - if (!matching_early_clobber[m]) - { - reject--; - matching_early_clobber[m] = 1; - } - } - /* Otherwise we prefer no matching - alternatives because it gives more freedom - in RA. */ - else if (operand_reg[nop] == NULL_RTX - || (find_regno_note (curr_insn, REG_DEAD, - REGNO (operand_reg[nop])) - == NULL_RTX)) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Matching alt: reject+=2\n", - nop); - reject += 2; - } - } - /* If we have to reload this operand and some - previous operand also had to match the same - thing as this operand, we don't know how to do - that. */ - if (!match_p || !curr_alt_win[m]) - { - for (i = 0; i < nop; i++) - if (curr_alt_matches[i] == m) - break; - if (i < nop) - break; - } - else - did_match = true; - - this_alternative_matches = m; - /* This can be fixed with reloads if the operand - we are supposed to match can be fixed with - reloads. */ - badop = false; - this_alternative = curr_alt[m]; - this_alternative_set = curr_alt_set[m]; - winreg = this_alternative != NO_REGS; - break; - } - - case 'g': - if (MEM_P (op) - || general_constant_p (op) - || spilled_pseudo_p (op)) - win = true; - cl = GENERAL_REGS; - goto reg; - - default: - cn = lookup_constraint (p); - switch (get_constraint_type (cn)) - { - case CT_REGISTER: - cl = reg_class_for_constraint (cn); - if (cl != NO_REGS) - goto reg; - break; - - case CT_CONST_INT: - if (CONST_INT_P (op) - && insn_const_int_ok_for_constraint (INTVAL (op), cn)) - win = true; - break; - - case CT_MEMORY: - case CT_RELAXED_MEMORY: - if (MEM_P (op) - && satisfies_memory_constraint_p (op, cn)) - win = true; - else if (spilled_pseudo_p (op)) - win = true; - - /* If we didn't already win, we can reload constants - via force_const_mem or put the pseudo value into - memory, or make other memory by reloading the - address like for 'o'. */ - if (CONST_POOL_OK_P (mode, op) - || MEM_P (op) || REG_P (op) - /* We can restore the equiv insn by a - reload. */ - || equiv_substition_p[nop]) - badop = false; - constmemok = true; - offmemok = true; - break; - - case CT_ADDRESS: - /* An asm operand with an address constraint - that doesn't satisfy address_operand has - is_address cleared, so that we don't try to - make a non-address fit. */ - if (!curr_static_id->operand[nop].is_address) - break; - /* If we didn't already win, we can reload the address - into a base register. */ - if (satisfies_address_constraint_p (op, cn)) - win = true; - cl = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC, - ADDRESS, SCRATCH); - badop = false; - goto reg; - - case CT_FIXED_FORM: - if (constraint_satisfied_p (op, cn)) - win = true; - break; - - case CT_SPECIAL_MEMORY: - if (satisfies_memory_constraint_p (op, cn)) - win = true; - else if (spilled_pseudo_p (op)) - win = true; - break; - } - break; - - reg: - if (mode == BLKmode) - break; - this_alternative = reg_class_subunion[this_alternative][cl]; - this_alternative_set |= reg_class_contents[cl]; - if (costly_p) - { - this_costly_alternative - = reg_class_subunion[this_costly_alternative][cl]; - this_costly_alternative_set |= reg_class_contents[cl]; - } - winreg = true; - if (REG_P (op)) - { - if (hard_regno[nop] >= 0 - && in_hard_reg_set_p (this_alternative_set, - mode, hard_regno[nop])) - win = true; - else if (hard_regno[nop] < 0 - && in_class_p (op, this_alternative, NULL)) - win = true; - } - break; - } - if (c != ' ' && c != '\t') - costly_p = c == '*'; - } - while ((p += len), c); - - scratch_p = (operand_reg[nop] != NULL_RTX - && ira_former_scratch_p (REGNO (operand_reg[nop]))); - /* Record which operands fit this alternative. */ - if (win) - { - this_alternative_win = true; - if (operand_reg[nop] != NULL_RTX) - { - if (hard_regno[nop] >= 0) - { - if (in_hard_reg_set_p (this_costly_alternative_set, - mode, hard_regno[nop])) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " %d Costly set: reject++\n", - nop); - reject++; - } - } - else - { - /* Prefer won reg to spilled pseudo under other - equal conditions for possibe inheritance. */ - if (! scratch_p) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Non pseudo reload: reject++\n", - nop); - reject++; - } - if (in_class_p (operand_reg[nop], - this_costly_alternative, NULL)) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Non pseudo costly reload:" - " reject++\n", - nop); - reject++; - } - } - /* We simulate the behavior of old reload here. - Although scratches need hard registers and it - might result in spilling other pseudos, no reload - insns are generated for the scratches. So it - might cost something but probably less than old - reload pass believes. */ - if (scratch_p) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " %d Scratch win: reject+=2\n", - nop); - reject += 2; - } - } - } - else if (did_match) - this_alternative_match_win = true; - else - { - int const_to_mem = 0; - bool no_regs_p; - - reject += op_reject; - /* Never do output reload of stack pointer. It makes - impossible to do elimination when SP is changed in - RTL. */ - if (op == stack_pointer_rtx && ! frame_pointer_needed - && curr_static_id->operand[nop].type != OP_IN) - goto fail; - - /* If this alternative asks for a specific reg class, see if there - is at least one allocatable register in that class. */ - no_regs_p - = (this_alternative == NO_REGS - || (hard_reg_set_subset_p - (reg_class_contents[this_alternative], - lra_no_alloc_regs))); - - /* For asms, verify that the class for this alternative is possible - for the mode that is specified. */ - if (!no_regs_p && INSN_CODE (curr_insn) < 0) - { - int i; - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (targetm.hard_regno_mode_ok (i, mode) - && in_hard_reg_set_p (reg_class_contents[this_alternative], - mode, i)) - break; - if (i == FIRST_PSEUDO_REGISTER) - winreg = false; - } - - /* If this operand accepts a register, and if the - register class has at least one allocatable register, - then this operand can be reloaded. */ - if (winreg && !no_regs_p) - badop = false; - - if (badop) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " alt=%d: Bad operand -- refuse\n", - nalt); - goto fail; - } - - if (this_alternative != NO_REGS) - { - HARD_REG_SET available_regs - = (reg_class_contents[this_alternative] - & ~((ira_prohibited_class_mode_regs - [this_alternative][mode]) - | lra_no_alloc_regs)); - if (hard_reg_set_empty_p (available_regs)) - { - /* There are no hard regs holding a value of given - mode. */ - if (offmemok) - { - this_alternative = NO_REGS; - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " %d Using memory because of" - " a bad mode: reject+=2\n", - nop); - reject += 2; - } - else - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " alt=%d: Wrong mode -- refuse\n", - nalt); - goto fail; - } - } - } - - /* If not assigned pseudo has a class which a subset of - required reg class, it is a less costly alternative - as the pseudo still can get a hard reg of necessary - class. */ - if (! no_regs_p && REG_P (op) && hard_regno[nop] < 0 - && (cl = get_reg_class (REGNO (op))) != NO_REGS - && ira_class_subset_p[this_alternative][cl]) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Super set class reg: reject-=3\n", nop); - reject -= 3; - } - - this_alternative_offmemok = offmemok; - if (this_costly_alternative != NO_REGS) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " %d Costly loser: reject++\n", nop); - reject++; - } - /* If the operand is dying, has a matching constraint, - and satisfies constraints of the matched operand - which failed to satisfy the own constraints, most probably - the reload for this operand will be gone. */ - if (this_alternative_matches >= 0 - && !curr_alt_win[this_alternative_matches] - && REG_P (op) - && find_regno_note (curr_insn, REG_DEAD, REGNO (op)) - && (hard_regno[nop] >= 0 - ? in_hard_reg_set_p (this_alternative_set, - mode, hard_regno[nop]) - : in_class_p (op, this_alternative, NULL))) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Dying matched operand reload: reject++\n", - nop); - reject++; - } - else - { - /* Strict_low_part requires to reload the register - not the sub-register. In this case we should - check that a final reload hard reg can hold the - value mode. */ - if (curr_static_id->operand[nop].strict_low - && REG_P (op) - && hard_regno[nop] < 0 - && GET_CODE (*curr_id->operand_loc[nop]) == SUBREG - && ira_class_hard_regs_num[this_alternative] > 0 - && (!targetm.hard_regno_mode_ok - (ira_class_hard_regs[this_alternative][0], - GET_MODE (*curr_id->operand_loc[nop])))) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " alt=%d: Strict low subreg reload -- refuse\n", - nalt); - goto fail; - } - losers++; - } - if (operand_reg[nop] != NULL_RTX - /* Output operands and matched input operands are - not inherited. The following conditions do not - exactly describe the previous statement but they - are pretty close. */ - && curr_static_id->operand[nop].type != OP_OUT - && (this_alternative_matches < 0 - || curr_static_id->operand[nop].type != OP_IN)) - { - int last_reload = (lra_reg_info[ORIGINAL_REGNO - (operand_reg[nop])] - .last_reload); - - /* The value of reload_sum has sense only if we - process insns in their order. It happens only on - the first constraints sub-pass when we do most of - reload work. */ - if (lra_constraint_iter == 1 && last_reload > bb_reload_num) - reload_sum += last_reload - bb_reload_num; - } - /* If this is a constant that is reloaded into the - desired class by copying it to memory first, count - that as another reload. This is consistent with - other code and is required to avoid choosing another - alternative when the constant is moved into memory. - Note that the test here is precisely the same as in - the code below that calls force_const_mem. */ - if (CONST_POOL_OK_P (mode, op) - && ((targetm.preferred_reload_class - (op, this_alternative) == NO_REGS) - || no_input_reloads_p)) - { - const_to_mem = 1; - if (! no_regs_p) - losers++; - } - - /* Alternative loses if it requires a type of reload not - permitted for this insn. We can always reload - objects with a REG_UNUSED note. */ - if ((curr_static_id->operand[nop].type != OP_IN - && no_output_reloads_p - && ! find_reg_note (curr_insn, REG_UNUSED, op)) - || (curr_static_id->operand[nop].type != OP_OUT - && no_input_reloads_p && ! const_to_mem) - || (this_alternative_matches >= 0 - && (no_input_reloads_p - || (no_output_reloads_p - && (curr_static_id->operand - [this_alternative_matches].type != OP_IN) - && ! find_reg_note (curr_insn, REG_UNUSED, - no_subreg_reg_operand - [this_alternative_matches]))))) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " alt=%d: No input/output reload -- refuse\n", - nalt); - goto fail; - } - - /* Alternative loses if it required class pseudo cannot - hold value of required mode. Such insns can be - described by insn definitions with mode iterators. */ - if (GET_MODE (*curr_id->operand_loc[nop]) != VOIDmode - && ! hard_reg_set_empty_p (this_alternative_set) - /* It is common practice for constraints to use a - class which does not have actually enough regs to - hold the value (e.g. x86 AREG for mode requiring - more one general reg). Therefore we have 2 - conditions to check that the reload pseudo cannot - hold the mode value. */ - && (!targetm.hard_regno_mode_ok - (ira_class_hard_regs[this_alternative][0], - GET_MODE (*curr_id->operand_loc[nop]))) - /* The above condition is not enough as the first - reg in ira_class_hard_regs can be not aligned for - multi-words mode values. */ - && (prohibited_class_reg_set_mode_p - (this_alternative, this_alternative_set, - GET_MODE (*curr_id->operand_loc[nop])))) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " alt=%d: reload pseudo for op %d " - "cannot hold the mode value -- refuse\n", - nalt, nop); - goto fail; - } - - /* Check strong discouragement of reload of non-constant - into class THIS_ALTERNATIVE. */ - if (! CONSTANT_P (op) && ! no_regs_p - && (targetm.preferred_reload_class - (op, this_alternative) == NO_REGS - || (curr_static_id->operand[nop].type == OP_OUT - && (targetm.preferred_output_reload_class - (op, this_alternative) == NO_REGS)))) - { - if (offmemok && REG_P (op)) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Spill pseudo into memory: reject+=3\n", - nop); - reject += 3; - } - else - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Non-prefered reload: reject+=%d\n", - nop, LRA_MAX_REJECT); - reject += LRA_MAX_REJECT; - } - } - - if (! (MEM_P (op) && offmemok) - && ! (const_to_mem && constmemok)) - { - /* We prefer to reload pseudos over reloading other - things, since such reloads may be able to be - eliminated later. So bump REJECT in other cases. - Don't do this in the case where we are forcing a - constant into memory and it will then win since - we don't want to have a different alternative - match then. */ - if (! (REG_P (op) && REGNO (op) >= FIRST_PSEUDO_REGISTER)) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Non-pseudo reload: reject+=2\n", - nop); - reject += 2; - } - - if (! no_regs_p) - reload_nregs - += ira_reg_class_max_nregs[this_alternative][mode]; - - if (SMALL_REGISTER_CLASS_P (this_alternative)) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Small class reload: reject+=%d\n", - nop, LRA_LOSER_COST_FACTOR / 2); - reject += LRA_LOSER_COST_FACTOR / 2; - } - } - - /* We are trying to spill pseudo into memory. It is - usually more costly than moving to a hard register - although it might takes the same number of - reloads. - - Non-pseudo spill may happen also. Suppose a target allows both - register and memory in the operand constraint alternatives, - then it's typical that an eliminable register has a substition - of "base + offset" which can either be reloaded by a simple - "new_reg <= base + offset" which will match the register - constraint, or a similar reg addition followed by further spill - to and reload from memory which will match the memory - constraint, but this memory spill will be much more costly - usually. - - Code below increases the reject for both pseudo and non-pseudo - spill. */ - if (no_regs_p - && !(MEM_P (op) && offmemok) - && !(REG_P (op) && hard_regno[nop] < 0)) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Spill %spseudo into memory: reject+=3\n", - nop, REG_P (op) ? "" : "Non-"); - reject += 3; - if (VECTOR_MODE_P (mode)) - { - /* Spilling vectors into memory is usually more - costly as they contain big values. */ - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Spill vector pseudo: reject+=2\n", - nop); - reject += 2; - } - } - - /* When we use an operand requiring memory in given - alternative, the insn should write *and* read the - value to/from memory it is costly in comparison with - an insn alternative which does not use memory - (e.g. register or immediate operand). We exclude - memory operand for such case as we can satisfy the - memory constraints by reloading address. */ - if (no_regs_p && offmemok && !MEM_P (op)) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " Using memory insn operand %d: reject+=3\n", - nop); - reject += 3; - } - - /* If reload requires moving value through secondary - memory, it will need one more insn at least. */ - if (this_alternative != NO_REGS - && REG_P (op) && (cl = get_reg_class (REGNO (op))) != NO_REGS - && ((curr_static_id->operand[nop].type != OP_OUT - && targetm.secondary_memory_needed (GET_MODE (op), cl, - this_alternative)) - || (curr_static_id->operand[nop].type != OP_IN - && (targetm.secondary_memory_needed - (GET_MODE (op), this_alternative, cl))))) - losers++; - - if (MEM_P (op) && offmemok) - addr_losers++; - else - { - /* Input reloads can be inherited more often than - output reloads can be removed, so penalize output - reloads. */ - if (!REG_P (op) || curr_static_id->operand[nop].type != OP_IN) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Non input pseudo reload: reject++\n", - nop); - reject++; - } - - if (curr_static_id->operand[nop].type == OP_INOUT) - { - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Input/Output reload: reject+=%d\n", - nop, LRA_LOSER_COST_FACTOR); - reject += LRA_LOSER_COST_FACTOR; - } - } - } - - if (early_clobber_p && ! scratch_p) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " %d Early clobber: reject++\n", nop); - reject++; - } - /* ??? We check early clobbers after processing all operands - (see loop below) and there we update the costs more. - Should we update the cost (may be approximately) here - because of early clobber register reloads or it is a rare - or non-important thing to be worth to do it. */ - overall = (losers * LRA_LOSER_COST_FACTOR + reject - - (addr_losers == losers ? static_reject : 0)); - if ((best_losers == 0 || losers != 0) && best_overall < overall) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " alt=%d,overall=%d,losers=%d -- refuse\n", - nalt, overall, losers); - goto fail; - } - - if (update_and_check_small_class_inputs (nop, nalt, - this_alternative)) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " alt=%d, not enough small class regs -- refuse\n", - nalt); - goto fail; - } - curr_alt[nop] = this_alternative; - curr_alt_set[nop] = this_alternative_set; - curr_alt_win[nop] = this_alternative_win; - curr_alt_match_win[nop] = this_alternative_match_win; - curr_alt_offmemok[nop] = this_alternative_offmemok; - curr_alt_matches[nop] = this_alternative_matches; - - if (this_alternative_matches >= 0 - && !did_match && !this_alternative_win) - curr_alt_win[this_alternative_matches] = false; - - if (early_clobber_p && operand_reg[nop] != NULL_RTX) - early_clobbered_nops[early_clobbered_regs_num++] = nop; - } - - if (curr_insn_set != NULL_RTX && n_operands == 2 - /* Prevent processing non-move insns. */ - && (GET_CODE (SET_SRC (curr_insn_set)) == SUBREG - || SET_SRC (curr_insn_set) == no_subreg_reg_operand[1]) - && ((! curr_alt_win[0] && ! curr_alt_win[1] - && REG_P (no_subreg_reg_operand[0]) - && REG_P (no_subreg_reg_operand[1]) - && (reg_in_class_p (no_subreg_reg_operand[0], curr_alt[1]) - || reg_in_class_p (no_subreg_reg_operand[1], curr_alt[0]))) - || (! curr_alt_win[0] && curr_alt_win[1] - && REG_P (no_subreg_reg_operand[1]) - /* Check that we reload memory not the memory - address. */ - && ! (curr_alt_offmemok[0] - && MEM_P (no_subreg_reg_operand[0])) - && reg_in_class_p (no_subreg_reg_operand[1], curr_alt[0])) - || (curr_alt_win[0] && ! curr_alt_win[1] - && REG_P (no_subreg_reg_operand[0]) - /* Check that we reload memory not the memory - address. */ - && ! (curr_alt_offmemok[1] - && MEM_P (no_subreg_reg_operand[1])) - && reg_in_class_p (no_subreg_reg_operand[0], curr_alt[1]) - && (! CONST_POOL_OK_P (curr_operand_mode[1], - no_subreg_reg_operand[1]) - || (targetm.preferred_reload_class - (no_subreg_reg_operand[1], - (enum reg_class) curr_alt[1]) != NO_REGS)) - /* If it is a result of recent elimination in move - insn we can transform it into an add still by - using this alternative. */ - && GET_CODE (no_subreg_reg_operand[1]) != PLUS - /* Likewise if the source has been replaced with an - equivalent value. This only happens once -- the reload - will use the equivalent value instead of the register it - replaces -- so there should be no danger of cycling. */ - && !equiv_substition_p[1]))) - { - /* We have a move insn and a new reload insn will be similar - to the current insn. We should avoid such situation as - it results in LRA cycling. */ - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " Cycle danger: overall += LRA_MAX_REJECT\n"); - overall += LRA_MAX_REJECT; - } - ok_p = true; - curr_alt_dont_inherit_ops_num = 0; - for (nop = 0; nop < early_clobbered_regs_num; nop++) - { - int i, j, clobbered_hard_regno, first_conflict_j, last_conflict_j; - HARD_REG_SET temp_set; - - i = early_clobbered_nops[nop]; - if ((! curr_alt_win[i] && ! curr_alt_match_win[i]) - || hard_regno[i] < 0) - continue; - lra_assert (operand_reg[i] != NULL_RTX); - clobbered_hard_regno = hard_regno[i]; - CLEAR_HARD_REG_SET (temp_set); - add_to_hard_reg_set (&temp_set, biggest_mode[i], clobbered_hard_regno); - first_conflict_j = last_conflict_j = -1; - for (j = 0; j < n_operands; j++) - if (j == i - /* We don't want process insides of match_operator and - match_parallel because otherwise we would process - their operands once again generating a wrong - code. */ - || curr_static_id->operand[j].is_operator) - continue; - else if ((curr_alt_matches[j] == i && curr_alt_match_win[j]) - || (curr_alt_matches[i] == j && curr_alt_match_win[i])) - continue; - /* If we don't reload j-th operand, check conflicts. */ - else if ((curr_alt_win[j] || curr_alt_match_win[j]) - && uses_hard_regs_p (*curr_id->operand_loc[j], temp_set)) - { - if (first_conflict_j < 0) - first_conflict_j = j; - last_conflict_j = j; - /* Both the earlyclobber operand and conflicting operand - cannot both be user defined hard registers. */ - if (HARD_REGISTER_P (operand_reg[i]) - && REG_USERVAR_P (operand_reg[i]) - && operand_reg[j] != NULL_RTX - && HARD_REGISTER_P (operand_reg[j]) - && REG_USERVAR_P (operand_reg[j])) - { - /* For asm, let curr_insn_transform diagnose it. */ - if (INSN_CODE (curr_insn) < 0) - return false; - fatal_insn ("unable to generate reloads for " - "impossible constraints:", curr_insn); - } - } - if (last_conflict_j < 0) - continue; - - /* If an earlyclobber operand conflicts with another non-matching - operand (ie, they have been assigned the same hard register), - then it is better to reload the other operand, as there may - exist yet another operand with a matching constraint associated - with the earlyclobber operand. However, if one of the operands - is an explicit use of a hard register, then we must reload the - other non-hard register operand. */ - if (HARD_REGISTER_P (operand_reg[i]) - || (first_conflict_j == last_conflict_j - && operand_reg[last_conflict_j] != NULL_RTX - && !curr_alt_match_win[last_conflict_j] - && !HARD_REGISTER_P (operand_reg[last_conflict_j]))) - { - curr_alt_win[last_conflict_j] = false; - curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++] - = last_conflict_j; - losers++; - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Conflict early clobber reload: reject--\n", - i); - } - else - { - /* We need to reload early clobbered register and the - matched registers. */ - for (j = 0; j < n_operands; j++) - if (curr_alt_matches[j] == i) - { - curr_alt_match_win[j] = false; - losers++; - overall += LRA_LOSER_COST_FACTOR; - } - if (! curr_alt_match_win[i]) - curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++] = i; - else - { - /* Remember pseudos used for match reloads are never - inherited. */ - lra_assert (curr_alt_matches[i] >= 0); - curr_alt_win[curr_alt_matches[i]] = false; - } - curr_alt_win[i] = curr_alt_match_win[i] = false; - losers++; - if (lra_dump_file != NULL) - fprintf - (lra_dump_file, - " %d Matched conflict early clobber reloads: " - "reject--\n", - i); - } - /* Early clobber was already reflected in REJECT. */ - if (!matching_early_clobber[i]) - { - lra_assert (reject > 0); - reject--; - matching_early_clobber[i] = 1; - } - overall += LRA_LOSER_COST_FACTOR - 1; - } - if (lra_dump_file != NULL) - fprintf (lra_dump_file, " alt=%d,overall=%d,losers=%d,rld_nregs=%d\n", - nalt, overall, losers, reload_nregs); - - /* If this alternative can be made to work by reloading, and it - needs less reloading than the others checked so far, record - it as the chosen goal for reloading. */ - if ((best_losers != 0 && losers == 0) - || (((best_losers == 0 && losers == 0) - || (best_losers != 0 && losers != 0)) - && (best_overall > overall - || (best_overall == overall - /* If the cost of the reloads is the same, - prefer alternative which requires minimal - number of reload regs. */ - && (reload_nregs < best_reload_nregs - || (reload_nregs == best_reload_nregs - && (best_reload_sum < reload_sum - || (best_reload_sum == reload_sum - && nalt < goal_alt_number)))))))) - { - for (nop = 0; nop < n_operands; nop++) - { - goal_alt_win[nop] = curr_alt_win[nop]; - goal_alt_match_win[nop] = curr_alt_match_win[nop]; - goal_alt_matches[nop] = curr_alt_matches[nop]; - goal_alt[nop] = curr_alt[nop]; - goal_alt_offmemok[nop] = curr_alt_offmemok[nop]; - } - goal_alt_dont_inherit_ops_num = curr_alt_dont_inherit_ops_num; - for (nop = 0; nop < curr_alt_dont_inherit_ops_num; nop++) - goal_alt_dont_inherit_ops[nop] = curr_alt_dont_inherit_ops[nop]; - goal_alt_swapped = curr_swapped; - best_overall = overall; - best_losers = losers; - best_reload_nregs = reload_nregs; - best_reload_sum = reload_sum; - goal_alt_number = nalt; - } - if (losers == 0) - /* Everything is satisfied. Do not process alternatives - anymore. */ - break; - fail: - ; - } - return ok_p; -} - -/* Make reload base reg from address AD. */ -static rtx -base_to_reg (struct address_info *ad) -{ - enum reg_class cl; - int code = -1; - rtx new_inner = NULL_RTX; - rtx new_reg = NULL_RTX; - rtx_insn *insn; - rtx_insn *last_insn = get_last_insn(); - - lra_assert (ad->disp == ad->disp_term); - cl = base_reg_class (ad->mode, ad->as, ad->base_outer_code, - get_index_code (ad)); - new_reg = lra_create_new_reg (GET_MODE (*ad->base), NULL_RTX, - cl, "base"); - new_inner = simplify_gen_binary (PLUS, GET_MODE (new_reg), new_reg, - ad->disp_term == NULL - ? const0_rtx - : *ad->disp_term); - if (!valid_address_p (ad->mode, new_inner, ad->as)) - return NULL_RTX; - insn = emit_insn (gen_rtx_SET (new_reg, *ad->base)); - code = recog_memoized (insn); - if (code < 0) - { - delete_insns_since (last_insn); - return NULL_RTX; - } - - return new_inner; -} - -/* Make reload base reg + DISP from address AD. Return the new pseudo. */ -static rtx -base_plus_disp_to_reg (struct address_info *ad, rtx disp) -{ - enum reg_class cl; - rtx new_reg; - - lra_assert (ad->base == ad->base_term); - cl = base_reg_class (ad->mode, ad->as, ad->base_outer_code, - get_index_code (ad)); - new_reg = lra_create_new_reg (GET_MODE (*ad->base_term), NULL_RTX, - cl, "base + disp"); - lra_emit_add (new_reg, *ad->base_term, disp); - return new_reg; -} - -/* Make reload of index part of address AD. Return the new - pseudo. */ -static rtx -index_part_to_reg (struct address_info *ad) -{ - rtx new_reg; - - new_reg = lra_create_new_reg (GET_MODE (*ad->index), NULL_RTX, - INDEX_REG_CLASS, "index term"); - expand_mult (GET_MODE (*ad->index), *ad->index_term, - GEN_INT (get_index_scale (ad)), new_reg, 1); - return new_reg; -} - -/* Return true if we can add a displacement to address AD, even if that - makes the address invalid. The fix-up code requires any new address - to be the sum of the BASE_TERM, INDEX and DISP_TERM fields. */ -static bool -can_add_disp_p (struct address_info *ad) -{ - return (!ad->autoinc_p - && ad->segment == NULL - && ad->base == ad->base_term - && ad->disp == ad->disp_term); -} - -/* Make equiv substitution in address AD. Return true if a substitution - was made. */ -static bool -equiv_address_substitution (struct address_info *ad) -{ - rtx base_reg, new_base_reg, index_reg, new_index_reg, *base_term, *index_term; - poly_int64 disp; - HOST_WIDE_INT scale; - bool change_p; - - base_term = strip_subreg (ad->base_term); - if (base_term == NULL) - base_reg = new_base_reg = NULL_RTX; - else - { - base_reg = *base_term; - new_base_reg = get_equiv_with_elimination (base_reg, curr_insn); - } - index_term = strip_subreg (ad->index_term); - if (index_term == NULL) - index_reg = new_index_reg = NULL_RTX; - else - { - index_reg = *index_term; - new_index_reg = get_equiv_with_elimination (index_reg, curr_insn); - } - if (base_reg == new_base_reg && index_reg == new_index_reg) - return false; - disp = 0; - change_p = false; - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, "Changing address in insn %d ", - INSN_UID (curr_insn)); - dump_value_slim (lra_dump_file, *ad->outer, 1); - } - if (base_reg != new_base_reg) - { - poly_int64 offset; - if (REG_P (new_base_reg)) - { - *base_term = new_base_reg; - change_p = true; - } - else if (GET_CODE (new_base_reg) == PLUS - && REG_P (XEXP (new_base_reg, 0)) - && poly_int_rtx_p (XEXP (new_base_reg, 1), &offset) - && can_add_disp_p (ad)) - { - disp += offset; - *base_term = XEXP (new_base_reg, 0); - change_p = true; - } - if (ad->base_term2 != NULL) - *ad->base_term2 = *ad->base_term; - } - if (index_reg != new_index_reg) - { - poly_int64 offset; - if (REG_P (new_index_reg)) - { - *index_term = new_index_reg; - change_p = true; - } - else if (GET_CODE (new_index_reg) == PLUS - && REG_P (XEXP (new_index_reg, 0)) - && poly_int_rtx_p (XEXP (new_index_reg, 1), &offset) - && can_add_disp_p (ad) - && (scale = get_index_scale (ad))) - { - disp += offset * scale; - *index_term = XEXP (new_index_reg, 0); - change_p = true; - } - } - if (maybe_ne (disp, 0)) - { - if (ad->disp != NULL) - *ad->disp = plus_constant (GET_MODE (*ad->inner), *ad->disp, disp); - else - { - *ad->inner = plus_constant (GET_MODE (*ad->inner), *ad->inner, disp); - update_address (ad); - } - change_p = true; - } - if (lra_dump_file != NULL) - { - if (! change_p) - fprintf (lra_dump_file, " -- no change\n"); - else - { - fprintf (lra_dump_file, " on equiv "); - dump_value_slim (lra_dump_file, *ad->outer, 1); - fprintf (lra_dump_file, "\n"); - } - } - return change_p; -} - -/* Skip all modifiers and whitespaces in constraint STR and return the - result. */ -static const char * -skip_constraint_modifiers (const char *str) -{ - for (;;str++) - switch (*str) - { - case '+': case '&' : case '=': case '*': case ' ': case '\t': - case '$': case '^' : case '%': case '?': case '!': - break; - default: return str; - } -} - -/* Major function to make reloads for an address in operand NOP or - check its correctness (If CHECK_ONLY_P is true). The supported - cases are: - - 1) an address that existed before LRA started, at which point it - must have been valid. These addresses are subject to elimination - and may have become invalid due to the elimination offset being out - of range. - - 2) an address created by forcing a constant to memory - (force_const_to_mem). The initial form of these addresses might - not be valid, and it is this function's job to make them valid. - - 3) a frame address formed from a register and a (possibly zero) - constant offset. As above, these addresses might not be valid and - this function must make them so. - - Add reloads to the lists *BEFORE and *AFTER. We might need to add - reloads to *AFTER because of inc/dec, {pre, post} modify in the - address. Return true for any RTL change. - - The function is a helper function which does not produce all - transformations (when CHECK_ONLY_P is false) which can be - necessary. It does just basic steps. To do all necessary - transformations use function process_address. */ -static bool -process_address_1 (int nop, bool check_only_p, - rtx_insn **before, rtx_insn **after) -{ - struct address_info ad; - rtx new_reg; - HOST_WIDE_INT scale; - rtx op = *curr_id->operand_loc[nop]; - rtx mem = extract_mem_from_operand (op); - const char *constraint; - enum constraint_num cn; - bool change_p = false; - - if (MEM_P (mem) - && GET_MODE (mem) == BLKmode - && GET_CODE (XEXP (mem, 0)) == SCRATCH) - return false; - - constraint - = skip_constraint_modifiers (curr_static_id->operand[nop].constraint); - if (IN_RANGE (constraint[0], '0', '9')) - { - char *end; - unsigned long dup = strtoul (constraint, &end, 10); - constraint - = skip_constraint_modifiers (curr_static_id->operand[dup].constraint); - } - cn = lookup_constraint (*constraint == '\0' ? "X" : constraint); - /* If we have several alternatives or/and several constraints in an - alternative and we can not say at this stage what constraint will be used, - use unknown constraint. The exception is an address constraint. If - operand has one address constraint, probably all others constraints are - address ones. */ - if (constraint[0] != '\0' && get_constraint_type (cn) != CT_ADDRESS - && *skip_constraint_modifiers (constraint - + CONSTRAINT_LEN (constraint[0], - constraint)) != '\0') - cn = CONSTRAINT__UNKNOWN; - if (insn_extra_address_constraint (cn) - /* When we find an asm operand with an address constraint that - doesn't satisfy address_operand to begin with, we clear - is_address, so that we don't try to make a non-address fit. - If the asm statement got this far, it's because other - constraints are available, and we'll use them, disregarding - the unsatisfiable address ones. */ - && curr_static_id->operand[nop].is_address) - decompose_lea_address (&ad, curr_id->operand_loc[nop]); - /* Do not attempt to decompose arbitrary addresses generated by combine - for asm operands with loose constraints, e.g 'X'. - Need to extract memory from op for special memory constraint, - i.e. bcst_mem_operand in i386 backend. */ - else if (MEM_P (mem) - && !(INSN_CODE (curr_insn) < 0 - && get_constraint_type (cn) == CT_FIXED_FORM - && constraint_satisfied_p (op, cn))) - decompose_mem_address (&ad, mem); - else if (GET_CODE (op) == SUBREG - && MEM_P (SUBREG_REG (op))) - decompose_mem_address (&ad, SUBREG_REG (op)); - else - return false; - /* If INDEX_REG_CLASS is assigned to base_term already and isn't to - index_term, swap them so to avoid assigning INDEX_REG_CLASS to both - when INDEX_REG_CLASS is a single register class. */ - if (ad.base_term != NULL - && ad.index_term != NULL - && ira_class_hard_regs_num[INDEX_REG_CLASS] == 1 - && REG_P (*ad.base_term) - && REG_P (*ad.index_term) - && in_class_p (*ad.base_term, INDEX_REG_CLASS, NULL) - && ! in_class_p (*ad.index_term, INDEX_REG_CLASS, NULL)) - { - std::swap (ad.base, ad.index); - std::swap (ad.base_term, ad.index_term); - } - if (! check_only_p) - change_p = equiv_address_substitution (&ad); - if (ad.base_term != NULL - && (process_addr_reg - (ad.base_term, check_only_p, before, - (ad.autoinc_p - && !(REG_P (*ad.base_term) - && find_regno_note (curr_insn, REG_DEAD, - REGNO (*ad.base_term)) != NULL_RTX) - ? after : NULL), - base_reg_class (ad.mode, ad.as, ad.base_outer_code, - get_index_code (&ad))))) - { - change_p = true; - if (ad.base_term2 != NULL) - *ad.base_term2 = *ad.base_term; - } - if (ad.index_term != NULL - && process_addr_reg (ad.index_term, check_only_p, - before, NULL, INDEX_REG_CLASS)) - change_p = true; - - /* Target hooks sometimes don't treat extra-constraint addresses as - legitimate address_operands, so handle them specially. */ - if (insn_extra_address_constraint (cn) - && satisfies_address_constraint_p (&ad, cn)) - return change_p; - - if (check_only_p) - return change_p; - - /* There are three cases where the shape of *AD.INNER may now be invalid: - - 1) the original address was valid, but either elimination or - equiv_address_substitution was applied and that made - the address invalid. - - 2) the address is an invalid symbolic address created by - force_const_to_mem. - - 3) the address is a frame address with an invalid offset. - - 4) the address is a frame address with an invalid base. - - All these cases involve a non-autoinc address, so there is no - point revalidating other types. */ - if (ad.autoinc_p || valid_address_p (op, &ad, cn)) - return change_p; - - /* Any index existed before LRA started, so we can assume that the - presence and shape of the index is valid. */ - push_to_sequence (*before); - lra_assert (ad.disp == ad.disp_term); - if (ad.base == NULL) - { - if (ad.index == NULL) - { - rtx_insn *insn; - rtx_insn *last = get_last_insn (); - int code = -1; - enum reg_class cl = base_reg_class (ad.mode, ad.as, - SCRATCH, SCRATCH); - rtx addr = *ad.inner; - - new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, "addr"); - if (HAVE_lo_sum) - { - /* addr => lo_sum (new_base, addr), case (2) above. */ - insn = emit_insn (gen_rtx_SET - (new_reg, - gen_rtx_HIGH (Pmode, copy_rtx (addr)))); - code = recog_memoized (insn); - if (code >= 0) - { - *ad.inner = gen_rtx_LO_SUM (Pmode, new_reg, addr); - if (!valid_address_p (op, &ad, cn)) - { - /* Try to put lo_sum into register. */ - insn = emit_insn (gen_rtx_SET - (new_reg, - gen_rtx_LO_SUM (Pmode, new_reg, addr))); - code = recog_memoized (insn); - if (code >= 0) - { - *ad.inner = new_reg; - if (!valid_address_p (op, &ad, cn)) - { - *ad.inner = addr; - code = -1; - } - } - - } - } - if (code < 0) - delete_insns_since (last); - } - - if (code < 0) - { - /* addr => new_base, case (2) above. */ - lra_emit_move (new_reg, addr); - - for (insn = last == NULL_RTX ? get_insns () : NEXT_INSN (last); - insn != NULL_RTX; - insn = NEXT_INSN (insn)) - if (recog_memoized (insn) < 0) - break; - if (insn != NULL_RTX) - { - /* Do nothing if we cannot generate right insns. - This is analogous to reload pass behavior. */ - delete_insns_since (last); - end_sequence (); - return false; - } - *ad.inner = new_reg; - } - } - else - { - /* index * scale + disp => new base + index * scale, - case (1) above. */ - enum reg_class cl = base_reg_class (ad.mode, ad.as, PLUS, - GET_CODE (*ad.index)); - - lra_assert (INDEX_REG_CLASS != NO_REGS); - new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, "disp"); - lra_emit_move (new_reg, *ad.disp); - *ad.inner = simplify_gen_binary (PLUS, GET_MODE (new_reg), - new_reg, *ad.index); - } - } - else if (ad.index == NULL) - { - int regno; - enum reg_class cl; - rtx set; - rtx_insn *insns, *last_insn; - /* Try to reload base into register only if the base is invalid - for the address but with valid offset, case (4) above. */ - start_sequence (); - new_reg = base_to_reg (&ad); - - /* base + disp => new base, cases (1) and (3) above. */ - /* Another option would be to reload the displacement into an - index register. However, postreload has code to optimize - address reloads that have the same base and different - displacements, so reloading into an index register would - not necessarily be a win. */ - if (new_reg == NULL_RTX) - { - /* See if the target can split the displacement into a - legitimate new displacement from a local anchor. */ - gcc_assert (ad.disp == ad.disp_term); - poly_int64 orig_offset; - rtx offset1, offset2; - if (poly_int_rtx_p (*ad.disp, &orig_offset) - && targetm.legitimize_address_displacement (&offset1, &offset2, - orig_offset, - ad.mode)) - { - new_reg = base_plus_disp_to_reg (&ad, offset1); - new_reg = gen_rtx_PLUS (GET_MODE (new_reg), new_reg, offset2); - } - else - new_reg = base_plus_disp_to_reg (&ad, *ad.disp); - } - insns = get_insns (); - last_insn = get_last_insn (); - /* If we generated at least two insns, try last insn source as - an address. If we succeed, we generate one less insn. */ - if (REG_P (new_reg) - && last_insn != insns - && (set = single_set (last_insn)) != NULL_RTX - && GET_CODE (SET_SRC (set)) == PLUS - && REG_P (XEXP (SET_SRC (set), 0)) - && CONSTANT_P (XEXP (SET_SRC (set), 1))) - { - *ad.inner = SET_SRC (set); - if (valid_address_p (op, &ad, cn)) - { - *ad.base_term = XEXP (SET_SRC (set), 0); - *ad.disp_term = XEXP (SET_SRC (set), 1); - cl = base_reg_class (ad.mode, ad.as, ad.base_outer_code, - get_index_code (&ad)); - regno = REGNO (*ad.base_term); - if (regno >= FIRST_PSEUDO_REGISTER - && cl != lra_get_allocno_class (regno)) - lra_change_class (regno, cl, " Change to", true); - new_reg = SET_SRC (set); - delete_insns_since (PREV_INSN (last_insn)); - } - } - end_sequence (); - emit_insn (insns); - *ad.inner = new_reg; - } - else if (ad.disp_term != NULL) - { - /* base + scale * index + disp => new base + scale * index, - case (1) above. */ - gcc_assert (ad.disp == ad.disp_term); - new_reg = base_plus_disp_to_reg (&ad, *ad.disp); - *ad.inner = simplify_gen_binary (PLUS, GET_MODE (new_reg), - new_reg, *ad.index); - } - else if ((scale = get_index_scale (&ad)) == 1) - { - /* The last transformation to one reg will be made in - curr_insn_transform function. */ - end_sequence (); - return false; - } - else if (scale != 0) - { - /* base + scale * index => base + new_reg, - case (1) above. - Index part of address may become invalid. For example, we - changed pseudo on the equivalent memory and a subreg of the - pseudo onto the memory of different mode for which the scale is - prohibitted. */ - new_reg = index_part_to_reg (&ad); - *ad.inner = simplify_gen_binary (PLUS, GET_MODE (new_reg), - *ad.base_term, new_reg); - } - else - { - enum reg_class cl = base_reg_class (ad.mode, ad.as, - SCRATCH, SCRATCH); - rtx addr = *ad.inner; - - new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, "addr"); - /* addr => new_base. */ - lra_emit_move (new_reg, addr); - *ad.inner = new_reg; - } - *before = get_insns (); - end_sequence (); - return true; -} - -/* If CHECK_ONLY_P is false, do address reloads until it is necessary. - Use process_address_1 as a helper function. Return true for any - RTL changes. - - If CHECK_ONLY_P is true, just check address correctness. Return - false if the address correct. */ -static bool -process_address (int nop, bool check_only_p, - rtx_insn **before, rtx_insn **after) -{ - bool res = false; - - while (process_address_1 (nop, check_only_p, before, after)) - { - if (check_only_p) - return true; - res = true; - } - return res; -} - -/* Emit insns to reload VALUE into a new register. VALUE is an - auto-increment or auto-decrement RTX whose operand is a register or - memory location; so reloading involves incrementing that location. - IN is either identical to VALUE, or some cheaper place to reload - value being incremented/decremented from. - - INC_AMOUNT is the number to increment or decrement by (always - positive and ignored for POST_MODIFY/PRE_MODIFY). - - Return pseudo containing the result. */ -static rtx -emit_inc (enum reg_class new_rclass, rtx in, rtx value, poly_int64 inc_amount) -{ - /* REG or MEM to be copied and incremented. */ - rtx incloc = XEXP (value, 0); - /* Nonzero if increment after copying. */ - int post = (GET_CODE (value) == POST_DEC || GET_CODE (value) == POST_INC - || GET_CODE (value) == POST_MODIFY); - rtx_insn *last; - rtx inc; - rtx_insn *add_insn; - int code; - rtx real_in = in == value ? incloc : in; - rtx result; - bool plus_p = true; - - if (GET_CODE (value) == PRE_MODIFY || GET_CODE (value) == POST_MODIFY) - { - lra_assert (GET_CODE (XEXP (value, 1)) == PLUS - || GET_CODE (XEXP (value, 1)) == MINUS); - lra_assert (rtx_equal_p (XEXP (XEXP (value, 1), 0), XEXP (value, 0))); - plus_p = GET_CODE (XEXP (value, 1)) == PLUS; - inc = XEXP (XEXP (value, 1), 1); - } - else - { - if (GET_CODE (value) == PRE_DEC || GET_CODE (value) == POST_DEC) - inc_amount = -inc_amount; - - inc = gen_int_mode (inc_amount, GET_MODE (value)); - } - - if (! post && REG_P (incloc)) - result = incloc; - else - result = lra_create_new_reg (GET_MODE (value), value, new_rclass, - "INC/DEC result"); - - if (real_in != result) - { - /* First copy the location to the result register. */ - lra_assert (REG_P (result)); - emit_insn (gen_move_insn (result, real_in)); - } - - /* We suppose that there are insns to add/sub with the constant - increment permitted in {PRE/POST)_{DEC/INC/MODIFY}. At least the - old reload worked with this assumption. If the assumption - becomes wrong, we should use approach in function - base_plus_disp_to_reg. */ - if (in == value) - { - /* See if we can directly increment INCLOC. */ - last = get_last_insn (); - add_insn = emit_insn (plus_p - ? gen_add2_insn (incloc, inc) - : gen_sub2_insn (incloc, inc)); - - code = recog_memoized (add_insn); - if (code >= 0) - { - if (! post && result != incloc) - emit_insn (gen_move_insn (result, incloc)); - return result; - } - delete_insns_since (last); - } - - /* If couldn't do the increment directly, must increment in RESULT. - The way we do this depends on whether this is pre- or - post-increment. For pre-increment, copy INCLOC to the reload - register, increment it there, then save back. */ - if (! post) - { - if (real_in != result) - emit_insn (gen_move_insn (result, real_in)); - if (plus_p) - emit_insn (gen_add2_insn (result, inc)); - else - emit_insn (gen_sub2_insn (result, inc)); - if (result != incloc) - emit_insn (gen_move_insn (incloc, result)); - } - else - { - /* Post-increment. - - Because this might be a jump insn or a compare, and because - RESULT may not be available after the insn in an input - reload, we must do the incrementing before the insn being - reloaded for. - - We have already copied IN to RESULT. Increment the copy in - RESULT, save that back, then decrement RESULT so it has - the original value. */ - if (plus_p) - emit_insn (gen_add2_insn (result, inc)); - else - emit_insn (gen_sub2_insn (result, inc)); - emit_insn (gen_move_insn (incloc, result)); - /* Restore non-modified value for the result. We prefer this - way because it does not require an additional hard - register. */ - if (plus_p) - { - poly_int64 offset; - if (poly_int_rtx_p (inc, &offset)) - emit_insn (gen_add2_insn (result, - gen_int_mode (-offset, - GET_MODE (result)))); - else - emit_insn (gen_sub2_insn (result, inc)); - } - else - emit_insn (gen_add2_insn (result, inc)); - } - return result; -} - -/* Return true if the current move insn does not need processing as we - already know that it satisfies its constraints. */ -static bool -simple_move_p (void) -{ - rtx dest, src; - enum reg_class dclass, sclass; - - lra_assert (curr_insn_set != NULL_RTX); - dest = SET_DEST (curr_insn_set); - src = SET_SRC (curr_insn_set); - - /* If the instruction has multiple sets we need to process it even if it - is single_set. This can happen if one or more of the SETs are dead. - See PR73650. */ - if (multiple_sets (curr_insn)) - return false; - - return ((dclass = get_op_class (dest)) != NO_REGS - && (sclass = get_op_class (src)) != NO_REGS - /* The backend guarantees that register moves of cost 2 - never need reloads. */ - && targetm.register_move_cost (GET_MODE (src), sclass, dclass) == 2); - } - -/* Swap operands NOP and NOP + 1. */ -static inline void -swap_operands (int nop) -{ - std::swap (curr_operand_mode[nop], curr_operand_mode[nop + 1]); - std::swap (original_subreg_reg_mode[nop], original_subreg_reg_mode[nop + 1]); - std::swap (*curr_id->operand_loc[nop], *curr_id->operand_loc[nop + 1]); - std::swap (equiv_substition_p[nop], equiv_substition_p[nop + 1]); - /* Swap the duplicates too. */ - lra_update_dup (curr_id, nop); - lra_update_dup (curr_id, nop + 1); -} - -/* Main entry point of the constraint code: search the body of the - current insn to choose the best alternative. It is mimicking insn - alternative cost calculation model of former reload pass. That is - because machine descriptions were written to use this model. This - model can be changed in future. Make commutative operand exchange - if it is chosen. - - if CHECK_ONLY_P is false, do RTL changes to satisfy the - constraints. Return true if any change happened during function - call. - - If CHECK_ONLY_P is true then don't do any transformation. Just - check that the insn satisfies all constraints. If the insn does - not satisfy any constraint, return true. */ -static bool -curr_insn_transform (bool check_only_p) -{ - int i, j, k; - int n_operands; - int n_alternatives; - int n_outputs; - int commutative; - signed char goal_alt_matched[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS]; - signed char match_inputs[MAX_RECOG_OPERANDS + 1]; - signed char outputs[MAX_RECOG_OPERANDS + 1]; - rtx_insn *before, *after; - bool alt_p = false; - /* Flag that the insn has been changed through a transformation. */ - bool change_p; - bool sec_mem_p; - bool use_sec_mem_p; - int max_regno_before; - int reused_alternative_num; - - curr_insn_set = single_set (curr_insn); - if (curr_insn_set != NULL_RTX && simple_move_p ()) - { - /* We assume that the corresponding insn alternative has no - earlier clobbers. If it is not the case, don't define move - cost equal to 2 for the corresponding register classes. */ - lra_set_used_insn_alternative (curr_insn, LRA_NON_CLOBBERED_ALT); - return false; - } - - no_input_reloads_p = no_output_reloads_p = false; - goal_alt_number = -1; - change_p = sec_mem_p = false; - - /* CALL_INSNs are not allowed to have any output reloads. */ - if (CALL_P (curr_insn)) - no_output_reloads_p = true; - - n_operands = curr_static_id->n_operands; - n_alternatives = curr_static_id->n_alternatives; - - /* Just return "no reloads" if insn has no operands with - constraints. */ - if (n_operands == 0 || n_alternatives == 0) - return false; - - max_regno_before = max_reg_num (); - - for (i = 0; i < n_operands; i++) - { - goal_alt_matched[i][0] = -1; - goal_alt_matches[i] = -1; - } - - commutative = curr_static_id->commutative; - - /* Now see what we need for pseudos that didn't get hard regs or got - the wrong kind of hard reg. For this, we must consider all the - operands together against the register constraints. */ - - best_losers = best_overall = INT_MAX; - best_reload_sum = 0; - - curr_swapped = false; - goal_alt_swapped = false; - - if (! check_only_p) - /* Make equivalence substitution and memory subreg elimination - before address processing because an address legitimacy can - depend on memory mode. */ - for (i = 0; i < n_operands; i++) - { - rtx op, subst, old; - bool op_change_p = false; - - if (curr_static_id->operand[i].is_operator) - continue; - - old = op = *curr_id->operand_loc[i]; - if (GET_CODE (old) == SUBREG) - old = SUBREG_REG (old); - subst = get_equiv_with_elimination (old, curr_insn); - original_subreg_reg_mode[i] = VOIDmode; - equiv_substition_p[i] = false; - if (subst != old) - { - equiv_substition_p[i] = true; - subst = copy_rtx (subst); - lra_assert (REG_P (old)); - if (GET_CODE (op) != SUBREG) - *curr_id->operand_loc[i] = subst; - else - { - SUBREG_REG (op) = subst; - if (GET_MODE (subst) == VOIDmode) - original_subreg_reg_mode[i] = GET_MODE (old); - } - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, - "Changing pseudo %d in operand %i of insn %u on equiv ", - REGNO (old), i, INSN_UID (curr_insn)); - dump_value_slim (lra_dump_file, subst, 1); - fprintf (lra_dump_file, "\n"); - } - op_change_p = change_p = true; - } - if (simplify_operand_subreg (i, GET_MODE (old)) || op_change_p) - { - change_p = true; - lra_update_dup (curr_id, i); - } - } - - /* Reload address registers and displacements. We do it before - finding an alternative because of memory constraints. */ - before = after = NULL; - for (i = 0; i < n_operands; i++) - if (! curr_static_id->operand[i].is_operator - && process_address (i, check_only_p, &before, &after)) - { - if (check_only_p) - return true; - change_p = true; - lra_update_dup (curr_id, i); - } - - if (change_p) - /* If we've changed the instruction then any alternative that - we chose previously may no longer be valid. */ - lra_set_used_insn_alternative (curr_insn, LRA_UNKNOWN_ALT); - - if (! check_only_p && curr_insn_set != NULL_RTX - && check_and_process_move (&change_p, &sec_mem_p)) - return change_p; - - try_swapped: - - reused_alternative_num = check_only_p ? LRA_UNKNOWN_ALT : curr_id->used_insn_alternative; - if (lra_dump_file != NULL && reused_alternative_num >= 0) - fprintf (lra_dump_file, "Reusing alternative %d for insn #%u\n", - reused_alternative_num, INSN_UID (curr_insn)); - - if (process_alt_operands (reused_alternative_num)) - alt_p = true; - - if (check_only_p) - return ! alt_p || best_losers != 0; - - /* If insn is commutative (it's safe to exchange a certain pair of - operands) then we need to try each alternative twice, the second - time matching those two operands as if we had exchanged them. To - do this, really exchange them in operands. - - If we have just tried the alternatives the second time, return - operands to normal and drop through. */ - - if (reused_alternative_num < 0 && commutative >= 0) - { - curr_swapped = !curr_swapped; - if (curr_swapped) - { - swap_operands (commutative); - goto try_swapped; - } - else - swap_operands (commutative); - } - - if (! alt_p && ! sec_mem_p) - { - /* No alternative works with reloads?? */ - if (INSN_CODE (curr_insn) >= 0) - fatal_insn ("unable to generate reloads for:", curr_insn); - error_for_asm (curr_insn, - "inconsistent operand constraints in an %<asm%>"); - lra_asm_error_p = true; - if (! JUMP_P (curr_insn)) - { - /* Avoid further trouble with this insn. Don't generate use - pattern here as we could use the insn SP offset. */ - lra_set_insn_deleted (curr_insn); - } - else - { - lra_invalidate_insn_data (curr_insn); - ira_nullify_asm_goto (curr_insn); - lra_update_insn_regno_info (curr_insn); - } - return true; - } - - /* If the best alternative is with operands 1 and 2 swapped, swap - them. Update the operand numbers of any reloads already - pushed. */ - - if (goal_alt_swapped) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, " Commutative operand exchange in insn %u\n", - INSN_UID (curr_insn)); - - /* Swap the duplicates too. */ - swap_operands (commutative); - change_p = true; - } - - /* Some targets' TARGET_SECONDARY_MEMORY_NEEDED (e.g. x86) are defined - too conservatively. So we use the secondary memory only if there - is no any alternative without reloads. */ - use_sec_mem_p = false; - if (! alt_p) - use_sec_mem_p = true; - else if (sec_mem_p) - { - for (i = 0; i < n_operands; i++) - if (! goal_alt_win[i] && ! goal_alt_match_win[i]) - break; - use_sec_mem_p = i < n_operands; - } - - if (use_sec_mem_p) - { - int in = -1, out = -1; - rtx new_reg, src, dest, rld; - machine_mode sec_mode, rld_mode; - - lra_assert (curr_insn_set != NULL_RTX && sec_mem_p); - dest = SET_DEST (curr_insn_set); - src = SET_SRC (curr_insn_set); - for (i = 0; i < n_operands; i++) - if (*curr_id->operand_loc[i] == dest) - out = i; - else if (*curr_id->operand_loc[i] == src) - in = i; - for (i = 0; i < curr_static_id->n_dups; i++) - if (out < 0 && *curr_id->dup_loc[i] == dest) - out = curr_static_id->dup_num[i]; - else if (in < 0 && *curr_id->dup_loc[i] == src) - in = curr_static_id->dup_num[i]; - lra_assert (out >= 0 && in >= 0 - && curr_static_id->operand[out].type == OP_OUT - && curr_static_id->operand[in].type == OP_IN); - rld = partial_subreg_p (GET_MODE (src), GET_MODE (dest)) ? src : dest; - rld_mode = GET_MODE (rld); - sec_mode = targetm.secondary_memory_needed_mode (rld_mode); - new_reg = lra_create_new_reg (sec_mode, NULL_RTX, - NO_REGS, "secondary"); - /* If the mode is changed, it should be wider. */ - lra_assert (!partial_subreg_p (sec_mode, rld_mode)); - if (sec_mode != rld_mode) - { - /* If the target says specifically to use another mode for - secondary memory moves we cannot reuse the original - insn. */ - after = emit_spill_move (false, new_reg, dest); - lra_process_new_insns (curr_insn, NULL, after, - "Inserting the sec. move"); - /* We may have non null BEFORE here (e.g. after address - processing. */ - push_to_sequence (before); - before = emit_spill_move (true, new_reg, src); - emit_insn (before); - before = get_insns (); - end_sequence (); - lra_process_new_insns (curr_insn, before, NULL, "Changing on"); - lra_set_insn_deleted (curr_insn); - } - else if (dest == rld) - { - *curr_id->operand_loc[out] = new_reg; - lra_update_dup (curr_id, out); - after = emit_spill_move (false, new_reg, dest); - lra_process_new_insns (curr_insn, NULL, after, - "Inserting the sec. move"); - } - else - { - *curr_id->operand_loc[in] = new_reg; - lra_update_dup (curr_id, in); - /* See comments above. */ - push_to_sequence (before); - before = emit_spill_move (true, new_reg, src); - emit_insn (before); - before = get_insns (); - end_sequence (); - lra_process_new_insns (curr_insn, before, NULL, - "Inserting the sec. move"); - } - lra_update_insn_regno_info (curr_insn); - return true; - } - - lra_assert (goal_alt_number >= 0); - lra_set_used_insn_alternative (curr_insn, goal_alt_number); - - if (lra_dump_file != NULL) - { - const char *p; - - fprintf (lra_dump_file, " Choosing alt %d in insn %u:", - goal_alt_number, INSN_UID (curr_insn)); - for (i = 0; i < n_operands; i++) - { - p = (curr_static_id->operand_alternative - [goal_alt_number * n_operands + i].constraint); - if (*p == '\0') - continue; - fprintf (lra_dump_file, " (%d) ", i); - for (; *p != '\0' && *p != ',' && *p != '#'; p++) - fputc (*p, lra_dump_file); - } - if (INSN_CODE (curr_insn) >= 0 - && (p = get_insn_name (INSN_CODE (curr_insn))) != NULL) - fprintf (lra_dump_file, " {%s}", p); - if (maybe_ne (curr_id->sp_offset, 0)) - { - fprintf (lra_dump_file, " (sp_off="); - print_dec (curr_id->sp_offset, lra_dump_file); - fprintf (lra_dump_file, ")"); - } - fprintf (lra_dump_file, "\n"); - } - - /* Right now, for any pair of operands I and J that are required to - match, with J < I, goal_alt_matches[I] is J. Add I to - goal_alt_matched[J]. */ - - for (i = 0; i < n_operands; i++) - if ((j = goal_alt_matches[i]) >= 0) - { - for (k = 0; goal_alt_matched[j][k] >= 0; k++) - ; - /* We allow matching one output operand and several input - operands. */ - lra_assert (k == 0 - || (curr_static_id->operand[j].type == OP_OUT - && curr_static_id->operand[i].type == OP_IN - && (curr_static_id->operand - [goal_alt_matched[j][0]].type == OP_IN))); - goal_alt_matched[j][k] = i; - goal_alt_matched[j][k + 1] = -1; - } - - for (i = 0; i < n_operands; i++) - goal_alt_win[i] |= goal_alt_match_win[i]; - - /* Any constants that aren't allowed and can't be reloaded into - registers are here changed into memory references. */ - for (i = 0; i < n_operands; i++) - if (goal_alt_win[i]) - { - int regno; - enum reg_class new_class; - rtx reg = *curr_id->operand_loc[i]; - - if (GET_CODE (reg) == SUBREG) - reg = SUBREG_REG (reg); - - if (REG_P (reg) && (regno = REGNO (reg)) >= FIRST_PSEUDO_REGISTER) - { - bool ok_p = in_class_p (reg, goal_alt[i], &new_class); - - if (new_class != NO_REGS && get_reg_class (regno) != new_class) - { - lra_assert (ok_p); - lra_change_class (regno, new_class, " Change to", true); - } - } - } - else - { - const char *constraint; - char c; - rtx op = *curr_id->operand_loc[i]; - rtx subreg = NULL_RTX; - machine_mode mode = curr_operand_mode[i]; - - if (GET_CODE (op) == SUBREG) - { - subreg = op; - op = SUBREG_REG (op); - mode = GET_MODE (op); - } - - if (CONST_POOL_OK_P (mode, op) - && ((targetm.preferred_reload_class - (op, (enum reg_class) goal_alt[i]) == NO_REGS) - || no_input_reloads_p)) - { - rtx tem = force_const_mem (mode, op); - - change_p = true; - if (subreg != NULL_RTX) - tem = gen_rtx_SUBREG (mode, tem, SUBREG_BYTE (subreg)); - - *curr_id->operand_loc[i] = tem; - lra_update_dup (curr_id, i); - process_address (i, false, &before, &after); - - /* If the alternative accepts constant pool refs directly - there will be no reload needed at all. */ - if (subreg != NULL_RTX) - continue; - /* Skip alternatives before the one requested. */ - constraint = (curr_static_id->operand_alternative - [goal_alt_number * n_operands + i].constraint); - for (; - (c = *constraint) && c != ',' && c != '#'; - constraint += CONSTRAINT_LEN (c, constraint)) - { - enum constraint_num cn = lookup_constraint (constraint); - if ((insn_extra_memory_constraint (cn) - || insn_extra_special_memory_constraint (cn) - || insn_extra_relaxed_memory_constraint (cn)) - && satisfies_memory_constraint_p (tem, cn)) - break; - } - if (c == '\0' || c == ',' || c == '#') - continue; - - goal_alt_win[i] = true; - } - } - - n_outputs = 0; - for (i = 0; i < n_operands; i++) - if (curr_static_id->operand[i].type == OP_OUT) - outputs[n_outputs++] = i; - outputs[n_outputs] = -1; - for (i = 0; i < n_operands; i++) - { - int regno; - bool optional_p = false; - rtx old, new_reg; - rtx op = *curr_id->operand_loc[i]; - - if (goal_alt_win[i]) - { - if (goal_alt[i] == NO_REGS - && REG_P (op) - /* When we assign NO_REGS it means that we will not - assign a hard register to the scratch pseudo by - assigment pass and the scratch pseudo will be - spilled. Spilled scratch pseudos are transformed - back to scratches at the LRA end. */ - && ira_former_scratch_operand_p (curr_insn, i) - && ira_former_scratch_p (REGNO (op))) - { - int regno = REGNO (op); - lra_change_class (regno, NO_REGS, " Change to", true); - if (lra_get_regno_hard_regno (regno) >= 0) - /* We don't have to mark all insn affected by the - spilled pseudo as there is only one such insn, the - current one. */ - reg_renumber[regno] = -1; - lra_assert (bitmap_single_bit_set_p - (&lra_reg_info[REGNO (op)].insn_bitmap)); - } - /* We can do an optional reload. If the pseudo got a hard - reg, we might improve the code through inheritance. If - it does not get a hard register we coalesce memory/memory - moves later. Ignore move insns to avoid cycling. */ - if (! lra_simple_p - && lra_undo_inheritance_iter < LRA_MAX_INHERITANCE_PASSES - && goal_alt[i] != NO_REGS && REG_P (op) - && (regno = REGNO (op)) >= FIRST_PSEUDO_REGISTER - && regno < new_regno_start - && ! ira_former_scratch_p (regno) - && reg_renumber[regno] < 0 - /* Check that the optional reload pseudo will be able to - hold given mode value. */ - && ! (prohibited_class_reg_set_mode_p - (goal_alt[i], reg_class_contents[goal_alt[i]], - PSEUDO_REGNO_MODE (regno))) - && (curr_insn_set == NULL_RTX - || !((REG_P (SET_SRC (curr_insn_set)) - || MEM_P (SET_SRC (curr_insn_set)) - || GET_CODE (SET_SRC (curr_insn_set)) == SUBREG) - && (REG_P (SET_DEST (curr_insn_set)) - || MEM_P (SET_DEST (curr_insn_set)) - || GET_CODE (SET_DEST (curr_insn_set)) == SUBREG)))) - optional_p = true; - else if (goal_alt_matched[i][0] != -1 - && curr_static_id->operand[i].type == OP_OUT - && (curr_static_id->operand_alternative - [goal_alt_number * n_operands + i].earlyclobber) - && REG_P (op)) - { - for (j = 0; goal_alt_matched[i][j] != -1; j++) - { - rtx op2 = *curr_id->operand_loc[goal_alt_matched[i][j]]; - - if (REG_P (op2) && REGNO (op) != REGNO (op2)) - break; - } - if (goal_alt_matched[i][j] != -1) - { - /* Generate reloads for different output and matched - input registers. This is the easiest way to avoid - creation of non-existing register conflicts in - lra-lives.c. */ - match_reload (i, goal_alt_matched[i], outputs, goal_alt[i], &before, - &after, TRUE); - } - continue; - } - else - continue; - } - - /* Operands that match previous ones have already been handled. */ - if (goal_alt_matches[i] >= 0) - continue; - - /* We should not have an operand with a non-offsettable address - appearing where an offsettable address will do. It also may - be a case when the address should be special in other words - not a general one (e.g. it needs no index reg). */ - if (goal_alt_matched[i][0] == -1 && goal_alt_offmemok[i] && MEM_P (op)) - { - enum reg_class rclass; - rtx *loc = &XEXP (op, 0); - enum rtx_code code = GET_CODE (*loc); - - push_to_sequence (before); - rclass = base_reg_class (GET_MODE (op), MEM_ADDR_SPACE (op), - MEM, SCRATCH); - if (GET_RTX_CLASS (code) == RTX_AUTOINC) - new_reg = emit_inc (rclass, *loc, *loc, - /* This value does not matter for MODIFY. */ - GET_MODE_SIZE (GET_MODE (op))); - else if (get_reload_reg (OP_IN, Pmode, *loc, rclass, FALSE, - "offsetable address", &new_reg)) - { - rtx addr = *loc; - enum rtx_code code = GET_CODE (addr); - bool align_p = false; - - if (code == AND && CONST_INT_P (XEXP (addr, 1))) - { - /* (and ... (const_int -X)) is used to align to X bytes. */ - align_p = true; - addr = XEXP (*loc, 0); - } - else - addr = canonicalize_reload_addr (addr); - - lra_emit_move (new_reg, addr); - if (align_p) - emit_move_insn (new_reg, gen_rtx_AND (GET_MODE (new_reg), new_reg, XEXP (*loc, 1))); - } - before = get_insns (); - end_sequence (); - *loc = new_reg; - lra_update_dup (curr_id, i); - } - else if (goal_alt_matched[i][0] == -1) - { - machine_mode mode; - rtx reg, *loc; - int hard_regno; - enum op_type type = curr_static_id->operand[i].type; - - loc = curr_id->operand_loc[i]; - mode = curr_operand_mode[i]; - if (GET_CODE (*loc) == SUBREG) - { - reg = SUBREG_REG (*loc); - poly_int64 byte = SUBREG_BYTE (*loc); - if (REG_P (reg) - /* Strict_low_part requires reloading the register and not - just the subreg. Likewise for a strict subreg no wider - than a word for WORD_REGISTER_OPERATIONS targets. */ - && (curr_static_id->operand[i].strict_low - || (!paradoxical_subreg_p (mode, GET_MODE (reg)) - && (hard_regno - = get_try_hard_regno (REGNO (reg))) >= 0 - && (simplify_subreg_regno - (hard_regno, - GET_MODE (reg), byte, mode) < 0) - && (goal_alt[i] == NO_REGS - || (simplify_subreg_regno - (ira_class_hard_regs[goal_alt[i]][0], - GET_MODE (reg), byte, mode) >= 0))) - || (partial_subreg_p (mode, GET_MODE (reg)) - && known_le (GET_MODE_SIZE (GET_MODE (reg)), - UNITS_PER_WORD) - && WORD_REGISTER_OPERATIONS))) - { - /* An OP_INOUT is required when reloading a subreg of a - mode wider than a word to ensure that data beyond the - word being reloaded is preserved. Also automatically - ensure that strict_low_part reloads are made into - OP_INOUT which should already be true from the backend - constraints. */ - if (type == OP_OUT - && (curr_static_id->operand[i].strict_low - || read_modify_subreg_p (*loc))) - type = OP_INOUT; - loc = &SUBREG_REG (*loc); - mode = GET_MODE (*loc); - } - } - old = *loc; - if (get_reload_reg (type, mode, old, goal_alt[i], - loc != curr_id->operand_loc[i], "", &new_reg) - && type != OP_OUT) - { - push_to_sequence (before); - lra_emit_move (new_reg, old); - before = get_insns (); - end_sequence (); - } - *loc = new_reg; - if (type != OP_IN - && find_reg_note (curr_insn, REG_UNUSED, old) == NULL_RTX) - { - start_sequence (); - lra_emit_move (type == OP_INOUT ? copy_rtx (old) : old, new_reg); - emit_insn (after); - after = get_insns (); - end_sequence (); - *loc = new_reg; - } - for (j = 0; j < goal_alt_dont_inherit_ops_num; j++) - if (goal_alt_dont_inherit_ops[j] == i) - { - lra_set_regno_unique_value (REGNO (new_reg)); - break; - } - lra_update_dup (curr_id, i); - } - else if (curr_static_id->operand[i].type == OP_IN - && (curr_static_id->operand[goal_alt_matched[i][0]].type - == OP_OUT - || (curr_static_id->operand[goal_alt_matched[i][0]].type - == OP_INOUT - && (operands_match_p - (*curr_id->operand_loc[i], - *curr_id->operand_loc[goal_alt_matched[i][0]], - -1))))) - { - /* generate reloads for input and matched outputs. */ - match_inputs[0] = i; - match_inputs[1] = -1; - match_reload (goal_alt_matched[i][0], match_inputs, outputs, - goal_alt[i], &before, &after, - curr_static_id->operand_alternative - [goal_alt_number * n_operands + goal_alt_matched[i][0]] - .earlyclobber); - } - else if ((curr_static_id->operand[i].type == OP_OUT - || (curr_static_id->operand[i].type == OP_INOUT - && (operands_match_p - (*curr_id->operand_loc[i], - *curr_id->operand_loc[goal_alt_matched[i][0]], - -1)))) - && (curr_static_id->operand[goal_alt_matched[i][0]].type - == OP_IN)) - /* Generate reloads for output and matched inputs. */ - match_reload (i, goal_alt_matched[i], outputs, goal_alt[i], &before, - &after, curr_static_id->operand_alternative - [goal_alt_number * n_operands + i].earlyclobber); - else if (curr_static_id->operand[i].type == OP_IN - && (curr_static_id->operand[goal_alt_matched[i][0]].type - == OP_IN)) - { - /* Generate reloads for matched inputs. */ - match_inputs[0] = i; - for (j = 0; (k = goal_alt_matched[i][j]) >= 0; j++) - match_inputs[j + 1] = k; - match_inputs[j + 1] = -1; - match_reload (-1, match_inputs, outputs, goal_alt[i], &before, - &after, false); - } - else - /* We must generate code in any case when function - process_alt_operands decides that it is possible. */ - gcc_unreachable (); - - if (optional_p) - { - rtx reg = op; - - lra_assert (REG_P (reg)); - regno = REGNO (reg); - op = *curr_id->operand_loc[i]; /* Substitution. */ - if (GET_CODE (op) == SUBREG) - op = SUBREG_REG (op); - gcc_assert (REG_P (op) && (int) REGNO (op) >= new_regno_start); - bitmap_set_bit (&lra_optional_reload_pseudos, REGNO (op)); - lra_reg_info[REGNO (op)].restore_rtx = reg; - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " Making reload reg %d for reg %d optional\n", - REGNO (op), regno); - } - } - if (before != NULL_RTX || after != NULL_RTX - || max_regno_before != max_reg_num ()) - change_p = true; - if (change_p) - { - lra_update_operator_dups (curr_id); - /* Something changes -- process the insn. */ - lra_update_insn_regno_info (curr_insn); - } - lra_process_new_insns (curr_insn, before, after, "Inserting insn reload"); - return change_p; -} - -/* Return true if INSN satisfies all constraints. In other words, no - reload insns are needed. */ -bool -lra_constrain_insn (rtx_insn *insn) -{ - int saved_new_regno_start = new_regno_start; - int saved_new_insn_uid_start = new_insn_uid_start; - bool change_p; - - curr_insn = insn; - curr_id = lra_get_insn_recog_data (curr_insn); - curr_static_id = curr_id->insn_static_data; - new_insn_uid_start = get_max_uid (); - new_regno_start = max_reg_num (); - change_p = curr_insn_transform (true); - new_regno_start = saved_new_regno_start; - new_insn_uid_start = saved_new_insn_uid_start; - return ! change_p; -} - -/* Return true if X is in LIST. */ -static bool -in_list_p (rtx x, rtx list) -{ - for (; list != NULL_RTX; list = XEXP (list, 1)) - if (XEXP (list, 0) == x) - return true; - return false; -} - -/* Return true if X contains an allocatable hard register (if - HARD_REG_P) or a (spilled if SPILLED_P) pseudo. */ -static bool -contains_reg_p (rtx x, bool hard_reg_p, bool spilled_p) -{ - int i, j; - const char *fmt; - enum rtx_code code; - - code = GET_CODE (x); - if (REG_P (x)) - { - int regno = REGNO (x); - HARD_REG_SET alloc_regs; - - if (hard_reg_p) - { - if (regno >= FIRST_PSEUDO_REGISTER) - regno = lra_get_regno_hard_regno (regno); - if (regno < 0) - return false; - alloc_regs = ~lra_no_alloc_regs; - return overlaps_hard_reg_set_p (alloc_regs, GET_MODE (x), regno); - } - else - { - if (regno < FIRST_PSEUDO_REGISTER) - return false; - if (! spilled_p) - return true; - return lra_get_regno_hard_regno (regno) < 0; - } - } - fmt = GET_RTX_FORMAT (code); - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - { - if (contains_reg_p (XEXP (x, i), hard_reg_p, spilled_p)) - return true; - } - else if (fmt[i] == 'E') - { - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - if (contains_reg_p (XVECEXP (x, i, j), hard_reg_p, spilled_p)) - return true; - } - } - return false; -} - -/* Process all regs in location *LOC and change them on equivalent - substitution. Return true if any change was done. */ -static bool -loc_equivalence_change_p (rtx *loc) -{ - rtx subst, reg, x = *loc; - bool result = false; - enum rtx_code code = GET_CODE (x); - const char *fmt; - int i, j; - - if (code == SUBREG) - { - reg = SUBREG_REG (x); - if ((subst = get_equiv_with_elimination (reg, curr_insn)) != reg - && GET_MODE (subst) == VOIDmode) - { - /* We cannot reload debug location. Simplify subreg here - while we know the inner mode. */ - *loc = simplify_gen_subreg (GET_MODE (x), subst, - GET_MODE (reg), SUBREG_BYTE (x)); - return true; - } - } - if (code == REG && (subst = get_equiv_with_elimination (x, curr_insn)) != x) - { - *loc = subst; - return true; - } - - /* Scan all the operand sub-expressions. */ - fmt = GET_RTX_FORMAT (code); - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - result = loc_equivalence_change_p (&XEXP (x, i)) || result; - else if (fmt[i] == 'E') - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - result - = loc_equivalence_change_p (&XVECEXP (x, i, j)) || result; - } - return result; -} - -/* Similar to loc_equivalence_change_p, but for use as - simplify_replace_fn_rtx callback. DATA is insn for which the - elimination is done. If it null we don't do the elimination. */ -static rtx -loc_equivalence_callback (rtx loc, const_rtx, void *data) -{ - if (!REG_P (loc)) - return NULL_RTX; - - rtx subst = (data == NULL - ? get_equiv (loc) : get_equiv_with_elimination (loc, (rtx_insn *) data)); - if (subst != loc) - return subst; - - return NULL_RTX; -} - -/* Maximum number of generated reload insns per an insn. It is for - preventing this pass cycling in a bug case. */ -#define MAX_RELOAD_INSNS_NUMBER LRA_MAX_INSN_RELOADS - -/* The current iteration number of this LRA pass. */ -int lra_constraint_iter; - -/* True if we should during assignment sub-pass check assignment - correctness for all pseudos and spill some of them to correct - conflicts. It can be necessary when we substitute equiv which - needs checking register allocation correctness because the - equivalent value contains allocatable hard registers, or when we - restore multi-register pseudo, or when we change the insn code and - its operand became INOUT operand when it was IN one before. */ -bool check_and_force_assignment_correctness_p; - -/* Return true if REGNO is referenced in more than one block. */ -static bool -multi_block_pseudo_p (int regno) -{ - basic_block bb = NULL; - unsigned int uid; - bitmap_iterator bi; - - if (regno < FIRST_PSEUDO_REGISTER) - return false; - - EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi) - if (bb == NULL) - bb = BLOCK_FOR_INSN (lra_insn_recog_data[uid]->insn); - else if (BLOCK_FOR_INSN (lra_insn_recog_data[uid]->insn) != bb) - return true; - return false; -} - -/* Return true if LIST contains a deleted insn. */ -static bool -contains_deleted_insn_p (rtx_insn_list *list) -{ - for (; list != NULL_RTX; list = list->next ()) - if (NOTE_P (list->insn ()) - && NOTE_KIND (list->insn ()) == NOTE_INSN_DELETED) - return true; - return false; -} - -/* Return true if X contains a pseudo dying in INSN. */ -static bool -dead_pseudo_p (rtx x, rtx_insn *insn) -{ - int i, j; - const char *fmt; - enum rtx_code code; - - if (REG_P (x)) - return (insn != NULL_RTX - && find_regno_note (insn, REG_DEAD, REGNO (x)) != NULL_RTX); - code = GET_CODE (x); - fmt = GET_RTX_FORMAT (code); - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - { - if (dead_pseudo_p (XEXP (x, i), insn)) - return true; - } - else if (fmt[i] == 'E') - { - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - if (dead_pseudo_p (XVECEXP (x, i, j), insn)) - return true; - } - } - return false; -} - -/* Return true if INSN contains a dying pseudo in INSN right hand - side. */ -static bool -insn_rhs_dead_pseudo_p (rtx_insn *insn) -{ - rtx set = single_set (insn); - - gcc_assert (set != NULL); - return dead_pseudo_p (SET_SRC (set), insn); -} - -/* Return true if any init insn of REGNO contains a dying pseudo in - insn right hand side. */ -static bool -init_insn_rhs_dead_pseudo_p (int regno) -{ - rtx_insn_list *insns = ira_reg_equiv[regno].init_insns; - - if (insns == NULL) - return false; - for (; insns != NULL_RTX; insns = insns->next ()) - if (insn_rhs_dead_pseudo_p (insns->insn ())) - return true; - return false; -} - -/* Return TRUE if REGNO has a reverse equivalence. The equivalence is - reverse only if we have one init insn with given REGNO as a - source. */ -static bool -reverse_equiv_p (int regno) -{ - rtx_insn_list *insns = ira_reg_equiv[regno].init_insns; - rtx set; - - if (insns == NULL) - return false; - if (! INSN_P (insns->insn ()) - || insns->next () != NULL) - return false; - if ((set = single_set (insns->insn ())) == NULL_RTX) - return false; - return REG_P (SET_SRC (set)) && (int) REGNO (SET_SRC (set)) == regno; -} - -/* Return TRUE if REGNO was reloaded in an equivalence init insn. We - call this function only for non-reverse equivalence. */ -static bool -contains_reloaded_insn_p (int regno) -{ - rtx set; - rtx_insn_list *list = ira_reg_equiv[regno].init_insns; - - for (; list != NULL; list = list->next ()) - if ((set = single_set (list->insn ())) == NULL_RTX - || ! REG_P (SET_DEST (set)) - || (int) REGNO (SET_DEST (set)) != regno) - return true; - return false; -} - -/* Entry function of LRA constraint pass. Return true if the - constraint pass did change the code. */ -bool -lra_constraints (bool first_p) -{ - bool changed_p; - int i, hard_regno, new_insns_num; - unsigned int min_len, new_min_len, uid; - rtx set, x, reg, dest_reg; - basic_block last_bb; - bitmap_iterator bi; - - lra_constraint_iter++; - if (lra_dump_file != NULL) - fprintf (lra_dump_file, "\n********** Local #%d: **********\n\n", - lra_constraint_iter); - changed_p = false; - if (pic_offset_table_rtx - && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER) - check_and_force_assignment_correctness_p = true; - else if (first_p) - /* On the first iteration we should check IRA assignment - correctness. In rare cases, the assignments can be wrong as - early clobbers operands are ignored in IRA or usages of - paradoxical sub-registers are not taken into account by - IRA. */ - check_and_force_assignment_correctness_p = true; - new_insn_uid_start = get_max_uid (); - new_regno_start = first_p ? lra_constraint_new_regno_start : max_reg_num (); - /* Mark used hard regs for target stack size calulations. */ - for (i = FIRST_PSEUDO_REGISTER; i < new_regno_start; i++) - if (lra_reg_info[i].nrefs != 0 - && (hard_regno = lra_get_regno_hard_regno (i)) >= 0) - { - int j, nregs; - - nregs = hard_regno_nregs (hard_regno, lra_reg_info[i].biggest_mode); - for (j = 0; j < nregs; j++) - df_set_regs_ever_live (hard_regno + j, true); - } - /* Do elimination before the equivalence processing as we can spill - some pseudos during elimination. */ - lra_eliminate (false, first_p); - auto_bitmap equiv_insn_bitmap (®_obstack); - for (i = FIRST_PSEUDO_REGISTER; i < new_regno_start; i++) - if (lra_reg_info[i].nrefs != 0) - { - ira_reg_equiv[i].profitable_p = true; - reg = regno_reg_rtx[i]; - if (lra_get_regno_hard_regno (i) < 0 && (x = get_equiv (reg)) != reg) - { - bool pseudo_p = contains_reg_p (x, false, false); - - /* After RTL transformation, we cannot guarantee that - pseudo in the substitution was not reloaded which might - make equivalence invalid. For example, in reverse - equiv of p0 - - p0 <- ... - ... - equiv_mem <- p0 - - the memory address register was reloaded before the 2nd - insn. */ - if ((! first_p && pseudo_p) - /* We don't use DF for compilation speed sake. So it - is problematic to update live info when we use an - equivalence containing pseudos in more than one - BB. */ - || (pseudo_p && multi_block_pseudo_p (i)) - /* If an init insn was deleted for some reason, cancel - the equiv. We could update the equiv insns after - transformations including an equiv insn deletion - but it is not worthy as such cases are extremely - rare. */ - || contains_deleted_insn_p (ira_reg_equiv[i].init_insns) - /* If it is not a reverse equivalence, we check that a - pseudo in rhs of the init insn is not dying in the - insn. Otherwise, the live info at the beginning of - the corresponding BB might be wrong after we - removed the insn. When the equiv can be a - constant, the right hand side of the init insn can - be a pseudo. */ - || (! reverse_equiv_p (i) - && (init_insn_rhs_dead_pseudo_p (i) - /* If we reloaded the pseudo in an equivalence - init insn, we cannot remove the equiv init - insns and the init insns might write into - const memory in this case. */ - || contains_reloaded_insn_p (i))) - /* Prevent access beyond equivalent memory for - paradoxical subregs. */ - || (MEM_P (x) - && maybe_gt (GET_MODE_SIZE (lra_reg_info[i].biggest_mode), - GET_MODE_SIZE (GET_MODE (x)))) - || (pic_offset_table_rtx - && ((CONST_POOL_OK_P (PSEUDO_REGNO_MODE (i), x) - && (targetm.preferred_reload_class - (x, lra_get_allocno_class (i)) == NO_REGS)) - || contains_symbol_ref_p (x)))) - ira_reg_equiv[i].defined_p = false; - if (contains_reg_p (x, false, true)) - ira_reg_equiv[i].profitable_p = false; - if (get_equiv (reg) != reg) - bitmap_ior_into (equiv_insn_bitmap, &lra_reg_info[i].insn_bitmap); - } - } - for (i = FIRST_PSEUDO_REGISTER; i < new_regno_start; i++) - update_equiv (i); - /* We should add all insns containing pseudos which should be - substituted by their equivalences. */ - EXECUTE_IF_SET_IN_BITMAP (equiv_insn_bitmap, 0, uid, bi) - lra_push_insn_by_uid (uid); - min_len = lra_insn_stack_length (); - new_insns_num = 0; - last_bb = NULL; - changed_p = false; - while ((new_min_len = lra_insn_stack_length ()) != 0) - { - curr_insn = lra_pop_insn (); - --new_min_len; - curr_bb = BLOCK_FOR_INSN (curr_insn); - if (curr_bb != last_bb) - { - last_bb = curr_bb; - bb_reload_num = lra_curr_reload_num; - } - if (min_len > new_min_len) - { - min_len = new_min_len; - new_insns_num = 0; - } - if (new_insns_num > MAX_RELOAD_INSNS_NUMBER) - internal_error - ("maximum number of generated reload insns per insn achieved (%d)", - MAX_RELOAD_INSNS_NUMBER); - new_insns_num++; - if (DEBUG_INSN_P (curr_insn)) - { - /* We need to check equivalence in debug insn and change - pseudo to the equivalent value if necessary. */ - curr_id = lra_get_insn_recog_data (curr_insn); - if (bitmap_bit_p (equiv_insn_bitmap, INSN_UID (curr_insn))) - { - rtx old = *curr_id->operand_loc[0]; - *curr_id->operand_loc[0] - = simplify_replace_fn_rtx (old, NULL_RTX, - loc_equivalence_callback, curr_insn); - if (old != *curr_id->operand_loc[0]) - { - lra_update_insn_regno_info (curr_insn); - changed_p = true; - } - } - } - else if (INSN_P (curr_insn)) - { - if ((set = single_set (curr_insn)) != NULL_RTX) - { - dest_reg = SET_DEST (set); - /* The equivalence pseudo could be set up as SUBREG in a - case when it is a call restore insn in a mode - different from the pseudo mode. */ - if (GET_CODE (dest_reg) == SUBREG) - dest_reg = SUBREG_REG (dest_reg); - if ((REG_P (dest_reg) - && (x = get_equiv (dest_reg)) != dest_reg - /* Remove insns which set up a pseudo whose value - cannot be changed. Such insns might be not in - init_insns because we don't update equiv data - during insn transformations. - - As an example, let suppose that a pseudo got - hard register and on the 1st pass was not - changed to equivalent constant. We generate an - additional insn setting up the pseudo because of - secondary memory movement. Then the pseudo is - spilled and we use the equiv constant. In this - case we should remove the additional insn and - this insn is not init_insns list. */ - && (! MEM_P (x) || MEM_READONLY_P (x) - /* Check that this is actually an insn setting - up the equivalence. */ - || in_list_p (curr_insn, - ira_reg_equiv - [REGNO (dest_reg)].init_insns))) - || (((x = get_equiv (SET_SRC (set))) != SET_SRC (set)) - && in_list_p (curr_insn, - ira_reg_equiv - [REGNO (SET_SRC (set))].init_insns))) - { - /* This is equiv init insn of pseudo which did not get a - hard register -- remove the insn. */ - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, - " Removing equiv init insn %i (freq=%d)\n", - INSN_UID (curr_insn), - REG_FREQ_FROM_BB (BLOCK_FOR_INSN (curr_insn))); - dump_insn_slim (lra_dump_file, curr_insn); - } - if (contains_reg_p (x, true, false)) - check_and_force_assignment_correctness_p = true; - lra_set_insn_deleted (curr_insn); - continue; - } - } - curr_id = lra_get_insn_recog_data (curr_insn); - curr_static_id = curr_id->insn_static_data; - init_curr_insn_input_reloads (); - init_curr_operand_mode (); - if (curr_insn_transform (false)) - changed_p = true; - /* Check non-transformed insns too for equiv change as USE - or CLOBBER don't need reloads but can contain pseudos - being changed on their equivalences. */ - else if (bitmap_bit_p (equiv_insn_bitmap, INSN_UID (curr_insn)) - && loc_equivalence_change_p (&PATTERN (curr_insn))) - { - lra_update_insn_regno_info (curr_insn); - changed_p = true; - } - } - } - - /* If we used a new hard regno, changed_p should be true because the - hard reg is assigned to a new pseudo. */ - if (flag_checking && !changed_p) - { - for (i = FIRST_PSEUDO_REGISTER; i < new_regno_start; i++) - if (lra_reg_info[i].nrefs != 0 - && (hard_regno = lra_get_regno_hard_regno (i)) >= 0) - { - int j, nregs = hard_regno_nregs (hard_regno, - PSEUDO_REGNO_MODE (i)); - - for (j = 0; j < nregs; j++) - lra_assert (df_regs_ever_live_p (hard_regno + j)); - } - } - return changed_p; -} - -static void initiate_invariants (void); -static void finish_invariants (void); - -/* Initiate the LRA constraint pass. It is done once per - function. */ -void -lra_constraints_init (void) -{ - initiate_invariants (); -} - -/* Finalize the LRA constraint pass. It is done once per - function. */ -void -lra_constraints_finish (void) -{ - finish_invariants (); -} - - - -/* Structure describes invariants for ineheritance. */ -struct lra_invariant -{ - /* The order number of the invariant. */ - int num; - /* The invariant RTX. */ - rtx invariant_rtx; - /* The origin insn of the invariant. */ - rtx_insn *insn; -}; - -typedef lra_invariant invariant_t; -typedef invariant_t *invariant_ptr_t; -typedef const invariant_t *const_invariant_ptr_t; - -/* Pointer to the inheritance invariants. */ -static vec<invariant_ptr_t> invariants; - -/* Allocation pool for the invariants. */ -static object_allocator<lra_invariant> *invariants_pool; - -/* Hash table for the invariants. */ -static htab_t invariant_table; - -/* Hash function for INVARIANT. */ -static hashval_t -invariant_hash (const void *invariant) -{ - rtx inv = ((const_invariant_ptr_t) invariant)->invariant_rtx; - return lra_rtx_hash (inv); -} - -/* Equal function for invariants INVARIANT1 and INVARIANT2. */ -static int -invariant_eq_p (const void *invariant1, const void *invariant2) -{ - rtx inv1 = ((const_invariant_ptr_t) invariant1)->invariant_rtx; - rtx inv2 = ((const_invariant_ptr_t) invariant2)->invariant_rtx; - - return rtx_equal_p (inv1, inv2); -} - -/* Insert INVARIANT_RTX into the table if it is not there yet. Return - invariant which is in the table. */ -static invariant_ptr_t -insert_invariant (rtx invariant_rtx) -{ - void **entry_ptr; - invariant_t invariant; - invariant_ptr_t invariant_ptr; - - invariant.invariant_rtx = invariant_rtx; - entry_ptr = htab_find_slot (invariant_table, &invariant, INSERT); - if (*entry_ptr == NULL) - { - invariant_ptr = invariants_pool->allocate (); - invariant_ptr->invariant_rtx = invariant_rtx; - invariant_ptr->insn = NULL; - invariants.safe_push (invariant_ptr); - *entry_ptr = (void *) invariant_ptr; - } - return (invariant_ptr_t) *entry_ptr; -} - -/* Initiate the invariant table. */ -static void -initiate_invariants (void) -{ - invariants.create (100); - invariants_pool - = new object_allocator<lra_invariant> ("Inheritance invariants"); - invariant_table = htab_create (100, invariant_hash, invariant_eq_p, NULL); -} - -/* Finish the invariant table. */ -static void -finish_invariants (void) -{ - htab_delete (invariant_table); - delete invariants_pool; - invariants.release (); -} - -/* Make the invariant table empty. */ -static void -clear_invariants (void) -{ - htab_empty (invariant_table); - invariants_pool->release (); - invariants.truncate (0); -} - - - -/* This page contains code to do inheritance/split - transformations. */ - -/* Number of reloads passed so far in current EBB. */ -static int reloads_num; - -/* Number of calls passed so far in current EBB. */ -static int calls_num; - -/* Index ID is the CALLS_NUM associated the last call we saw with - ABI identifier ID. */ -static int last_call_for_abi[NUM_ABI_IDS]; - -/* Which registers have been fully or partially clobbered by a call - since they were last used. */ -static HARD_REG_SET full_and_partial_call_clobbers; - -/* Current reload pseudo check for validity of elements in - USAGE_INSNS. */ -static int curr_usage_insns_check; - -/* Info about last usage of registers in EBB to do inheritance/split - transformation. Inheritance transformation is done from a spilled - pseudo and split transformations from a hard register or a pseudo - assigned to a hard register. */ -struct usage_insns -{ - /* If the value is equal to CURR_USAGE_INSNS_CHECK, then the member - value INSNS is valid. The insns is chain of optional debug insns - and a finishing non-debug insn using the corresponding reg. The - value is also used to mark the registers which are set up in the - current insn. The negated insn uid is used for this. */ - int check; - /* Value of global reloads_num at the last insn in INSNS. */ - int reloads_num; - /* Value of global reloads_nums at the last insn in INSNS. */ - int calls_num; - /* It can be true only for splitting. And it means that the restore - insn should be put after insn given by the following member. */ - bool after_p; - /* Next insns in the current EBB which use the original reg and the - original reg value is not changed between the current insn and - the next insns. In order words, e.g. for inheritance, if we need - to use the original reg value again in the next insns we can try - to use the value in a hard register from a reload insn of the - current insn. */ - rtx insns; -}; - -/* Map: regno -> corresponding pseudo usage insns. */ -static struct usage_insns *usage_insns; - -static void -setup_next_usage_insn (int regno, rtx insn, int reloads_num, bool after_p) -{ - usage_insns[regno].check = curr_usage_insns_check; - usage_insns[regno].insns = insn; - usage_insns[regno].reloads_num = reloads_num; - usage_insns[regno].calls_num = calls_num; - usage_insns[regno].after_p = after_p; - if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0) - remove_from_hard_reg_set (&full_and_partial_call_clobbers, - PSEUDO_REGNO_MODE (regno), - reg_renumber[regno]); -} - -/* The function is used to form list REGNO usages which consists of - optional debug insns finished by a non-debug insn using REGNO. - RELOADS_NUM is current number of reload insns processed so far. */ -static void -add_next_usage_insn (int regno, rtx_insn *insn, int reloads_num) -{ - rtx next_usage_insns; - - if (usage_insns[regno].check == curr_usage_insns_check - && (next_usage_insns = usage_insns[regno].insns) != NULL_RTX - && DEBUG_INSN_P (insn)) - { - /* Check that we did not add the debug insn yet. */ - if (next_usage_insns != insn - && (GET_CODE (next_usage_insns) != INSN_LIST - || XEXP (next_usage_insns, 0) != insn)) - usage_insns[regno].insns = gen_rtx_INSN_LIST (VOIDmode, insn, - next_usage_insns); - } - else if (NONDEBUG_INSN_P (insn)) - setup_next_usage_insn (regno, insn, reloads_num, false); - else - usage_insns[regno].check = 0; -} - -/* Return first non-debug insn in list USAGE_INSNS. */ -static rtx_insn * -skip_usage_debug_insns (rtx usage_insns) -{ - rtx insn; - - /* Skip debug insns. */ - for (insn = usage_insns; - insn != NULL_RTX && GET_CODE (insn) == INSN_LIST; - insn = XEXP (insn, 1)) - ; - return safe_as_a <rtx_insn *> (insn); -} - -/* Return true if we need secondary memory moves for insn in - USAGE_INSNS after inserting inherited pseudo of class INHER_CL - into the insn. */ -static bool -check_secondary_memory_needed_p (enum reg_class inher_cl ATTRIBUTE_UNUSED, - rtx usage_insns ATTRIBUTE_UNUSED) -{ - rtx_insn *insn; - rtx set, dest; - enum reg_class cl; - - if (inher_cl == ALL_REGS - || (insn = skip_usage_debug_insns (usage_insns)) == NULL_RTX) - return false; - lra_assert (INSN_P (insn)); - if ((set = single_set (insn)) == NULL_RTX || ! REG_P (SET_DEST (set))) - return false; - dest = SET_DEST (set); - if (! REG_P (dest)) - return false; - lra_assert (inher_cl != NO_REGS); - cl = get_reg_class (REGNO (dest)); - return (cl != NO_REGS && cl != ALL_REGS - && targetm.secondary_memory_needed (GET_MODE (dest), inher_cl, cl)); -} - -/* Registers involved in inheritance/split in the current EBB - (inheritance/split pseudos and original registers). */ -static bitmap_head check_only_regs; - -/* Reload pseudos cannot be involded in invariant inheritance in the - current EBB. */ -static bitmap_head invalid_invariant_regs; - -/* Do inheritance transformations for insn INSN, which defines (if - DEF_P) or uses ORIGINAL_REGNO. NEXT_USAGE_INSNS specifies which - instruction in the EBB next uses ORIGINAL_REGNO; it has the same - form as the "insns" field of usage_insns. Return true if we - succeed in such transformation. - - The transformations look like: - - p <- ... i <- ... - ... p <- i (new insn) - ... => - <- ... p ... <- ... i ... - or - ... i <- p (new insn) - <- ... p ... <- ... i ... - ... => - <- ... p ... <- ... i ... - where p is a spilled original pseudo and i is a new inheritance pseudo. - - - The inheritance pseudo has the smallest class of two classes CL and - class of ORIGINAL REGNO. */ -static bool -inherit_reload_reg (bool def_p, int original_regno, - enum reg_class cl, rtx_insn *insn, rtx next_usage_insns) -{ - if (optimize_function_for_size_p (cfun)) - return false; - - enum reg_class rclass = lra_get_allocno_class (original_regno); - rtx original_reg = regno_reg_rtx[original_regno]; - rtx new_reg, usage_insn; - rtx_insn *new_insns; - - lra_assert (! usage_insns[original_regno].after_p); - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); - if (! ira_reg_classes_intersect_p[cl][rclass]) - { - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, - " Rejecting inheritance for %d " - "because of disjoint classes %s and %s\n", - original_regno, reg_class_names[cl], - reg_class_names[rclass]); - fprintf (lra_dump_file, - " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - } - return false; - } - if ((ira_class_subset_p[cl][rclass] && cl != rclass) - /* We don't use a subset of two classes because it can be - NO_REGS. This transformation is still profitable in most - cases even if the classes are not intersected as register - move is probably cheaper than a memory load. */ - || ira_class_hard_regs_num[cl] < ira_class_hard_regs_num[rclass]) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, " Use smallest class of %s and %s\n", - reg_class_names[cl], reg_class_names[rclass]); - - rclass = cl; - } - if (check_secondary_memory_needed_p (rclass, next_usage_insns)) - { - /* Reject inheritance resulting in secondary memory moves. - Otherwise, there is a danger in LRA cycling. Also such - transformation will be unprofitable. */ - if (lra_dump_file != NULL) - { - rtx_insn *insn = skip_usage_debug_insns (next_usage_insns); - rtx set = single_set (insn); - - lra_assert (set != NULL_RTX); - - rtx dest = SET_DEST (set); - - lra_assert (REG_P (dest)); - fprintf (lra_dump_file, - " Rejecting inheritance for insn %d(%s)<-%d(%s) " - "as secondary mem is needed\n", - REGNO (dest), reg_class_names[get_reg_class (REGNO (dest))], - original_regno, reg_class_names[rclass]); - fprintf (lra_dump_file, - " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - } - return false; - } - new_reg = lra_create_new_reg (GET_MODE (original_reg), original_reg, - rclass, "inheritance"); - start_sequence (); - if (def_p) - lra_emit_move (original_reg, new_reg); - else - lra_emit_move (new_reg, original_reg); - new_insns = get_insns (); - end_sequence (); - if (NEXT_INSN (new_insns) != NULL_RTX) - { - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, - " Rejecting inheritance %d->%d " - "as it results in 2 or more insns:\n", - original_regno, REGNO (new_reg)); - dump_rtl_slim (lra_dump_file, new_insns, NULL, -1, 0); - fprintf (lra_dump_file, - " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - } - return false; - } - lra_substitute_pseudo_within_insn (insn, original_regno, new_reg, false); - lra_update_insn_regno_info (insn); - if (! def_p) - /* We now have a new usage insn for original regno. */ - setup_next_usage_insn (original_regno, new_insns, reloads_num, false); - if (lra_dump_file != NULL) - fprintf (lra_dump_file, " Original reg change %d->%d (bb%d):\n", - original_regno, REGNO (new_reg), BLOCK_FOR_INSN (insn)->index); - lra_reg_info[REGNO (new_reg)].restore_rtx = regno_reg_rtx[original_regno]; - bitmap_set_bit (&check_only_regs, REGNO (new_reg)); - bitmap_set_bit (&check_only_regs, original_regno); - bitmap_set_bit (&lra_inheritance_pseudos, REGNO (new_reg)); - if (def_p) - lra_process_new_insns (insn, NULL, new_insns, - "Add original<-inheritance"); - else - lra_process_new_insns (insn, new_insns, NULL, - "Add inheritance<-original"); - while (next_usage_insns != NULL_RTX) - { - if (GET_CODE (next_usage_insns) != INSN_LIST) - { - usage_insn = next_usage_insns; - lra_assert (NONDEBUG_INSN_P (usage_insn)); - next_usage_insns = NULL; - } - else - { - usage_insn = XEXP (next_usage_insns, 0); - lra_assert (DEBUG_INSN_P (usage_insn)); - next_usage_insns = XEXP (next_usage_insns, 1); - } - lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false, - DEBUG_INSN_P (usage_insn)); - lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn)); - if (lra_dump_file != NULL) - { - basic_block bb = BLOCK_FOR_INSN (usage_insn); - fprintf (lra_dump_file, - " Inheritance reuse change %d->%d (bb%d):\n", - original_regno, REGNO (new_reg), - bb ? bb->index : -1); - dump_insn_slim (lra_dump_file, as_a <rtx_insn *> (usage_insn)); - } - } - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - return true; -} - -/* Return true if we need a caller save/restore for pseudo REGNO which - was assigned to a hard register. */ -static inline bool -need_for_call_save_p (int regno) -{ - lra_assert (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0); - if (usage_insns[regno].calls_num < calls_num) - { - unsigned int abis = 0; - for (unsigned int i = 0; i < NUM_ABI_IDS; ++i) - if (last_call_for_abi[i] > usage_insns[regno].calls_num) - abis |= 1 << i; - gcc_assert (abis); - if (call_clobbered_in_region_p (abis, full_and_partial_call_clobbers, - PSEUDO_REGNO_MODE (regno), - reg_renumber[regno])) - return true; - } - return false; -} - -/* Global registers occurring in the current EBB. */ -static bitmap_head ebb_global_regs; - -/* Return true if we need a split for hard register REGNO or pseudo - REGNO which was assigned to a hard register. - POTENTIAL_RELOAD_HARD_REGS contains hard registers which might be - used for reloads since the EBB end. It is an approximation of the - used hard registers in the split range. The exact value would - require expensive calculations. If we were aggressive with - splitting because of the approximation, the split pseudo will save - the same hard register assignment and will be removed in the undo - pass. We still need the approximation because too aggressive - splitting would result in too inaccurate cost calculation in the - assignment pass because of too many generated moves which will be - probably removed in the undo pass. */ -static inline bool -need_for_split_p (HARD_REG_SET potential_reload_hard_regs, int regno) -{ - int hard_regno = regno < FIRST_PSEUDO_REGISTER ? regno : reg_renumber[regno]; - - lra_assert (hard_regno >= 0); - return ((TEST_HARD_REG_BIT (potential_reload_hard_regs, hard_regno) - /* Don't split eliminable hard registers, otherwise we can - split hard registers like hard frame pointer, which - lives on BB start/end according to DF-infrastructure, - when there is a pseudo assigned to the register and - living in the same BB. */ - && (regno >= FIRST_PSEUDO_REGISTER - || ! TEST_HARD_REG_BIT (eliminable_regset, hard_regno)) - && ! TEST_HARD_REG_BIT (lra_no_alloc_regs, hard_regno) - /* Don't split call clobbered hard regs living through - calls, otherwise we might have a check problem in the - assign sub-pass as in the most cases (exception is a - situation when check_and_force_assignment_correctness_p value is - true) the assign pass assumes that all pseudos living - through calls are assigned to call saved hard regs. */ - && (regno >= FIRST_PSEUDO_REGISTER - || !TEST_HARD_REG_BIT (full_and_partial_call_clobbers, regno)) - /* We need at least 2 reloads to make pseudo splitting - profitable. We should provide hard regno splitting in - any case to solve 1st insn scheduling problem when - moving hard register definition up might result in - impossibility to find hard register for reload pseudo of - small register class. */ - && (usage_insns[regno].reloads_num - + (regno < FIRST_PSEUDO_REGISTER ? 0 : 3) < reloads_num) - && (regno < FIRST_PSEUDO_REGISTER - /* For short living pseudos, spilling + inheritance can - be considered a substitution for splitting. - Therefore we do not splitting for local pseudos. It - decreases also aggressiveness of splitting. The - minimal number of references is chosen taking into - account that for 2 references splitting has no sense - as we can just spill the pseudo. */ - || (regno >= FIRST_PSEUDO_REGISTER - && lra_reg_info[regno].nrefs > 3 - && bitmap_bit_p (&ebb_global_regs, regno)))) - || (regno >= FIRST_PSEUDO_REGISTER && need_for_call_save_p (regno))); -} - -/* Return class for the split pseudo created from original pseudo with - ALLOCNO_CLASS and MODE which got a hard register HARD_REGNO. We - choose subclass of ALLOCNO_CLASS which contains HARD_REGNO and - results in no secondary memory movements. */ -static enum reg_class -choose_split_class (enum reg_class allocno_class, - int hard_regno ATTRIBUTE_UNUSED, - machine_mode mode ATTRIBUTE_UNUSED) -{ - int i; - enum reg_class cl, best_cl = NO_REGS; - enum reg_class hard_reg_class ATTRIBUTE_UNUSED - = REGNO_REG_CLASS (hard_regno); - - if (! targetm.secondary_memory_needed (mode, allocno_class, allocno_class) - && TEST_HARD_REG_BIT (reg_class_contents[allocno_class], hard_regno)) - return allocno_class; - for (i = 0; - (cl = reg_class_subclasses[allocno_class][i]) != LIM_REG_CLASSES; - i++) - if (! targetm.secondary_memory_needed (mode, cl, hard_reg_class) - && ! targetm.secondary_memory_needed (mode, hard_reg_class, cl) - && TEST_HARD_REG_BIT (reg_class_contents[cl], hard_regno) - && (best_cl == NO_REGS - || ira_class_hard_regs_num[best_cl] < ira_class_hard_regs_num[cl])) - best_cl = cl; - return best_cl; -} - -/* Copy any equivalence information from ORIGINAL_REGNO to NEW_REGNO. - It only makes sense to call this function if NEW_REGNO is always - equal to ORIGINAL_REGNO. */ - -static void -lra_copy_reg_equiv (unsigned int new_regno, unsigned int original_regno) -{ - if (!ira_reg_equiv[original_regno].defined_p) - return; - - ira_expand_reg_equiv (); - ira_reg_equiv[new_regno].defined_p = true; - if (ira_reg_equiv[original_regno].memory) - ira_reg_equiv[new_regno].memory - = copy_rtx (ira_reg_equiv[original_regno].memory); - if (ira_reg_equiv[original_regno].constant) - ira_reg_equiv[new_regno].constant - = copy_rtx (ira_reg_equiv[original_regno].constant); - if (ira_reg_equiv[original_regno].invariant) - ira_reg_equiv[new_regno].invariant - = copy_rtx (ira_reg_equiv[original_regno].invariant); -} - -/* Do split transformations for insn INSN, which defines or uses - ORIGINAL_REGNO. NEXT_USAGE_INSNS specifies which instruction in - the EBB next uses ORIGINAL_REGNO; it has the same form as the - "insns" field of usage_insns. If TO is not NULL, we don't use - usage_insns, we put restore insns after TO insn. It is a case when - we call it from lra_split_hard_reg_for, outside the inheritance - pass. - - The transformations look like: - - p <- ... p <- ... - ... s <- p (new insn -- save) - ... => - ... p <- s (new insn -- restore) - <- ... p ... <- ... p ... - or - <- ... p ... <- ... p ... - ... s <- p (new insn -- save) - ... => - ... p <- s (new insn -- restore) - <- ... p ... <- ... p ... - - where p is an original pseudo got a hard register or a hard - register and s is a new split pseudo. The save is put before INSN - if BEFORE_P is true. Return true if we succeed in such - transformation. */ -static bool -split_reg (bool before_p, int original_regno, rtx_insn *insn, - rtx next_usage_insns, rtx_insn *to) -{ - enum reg_class rclass; - rtx original_reg; - int hard_regno, nregs; - rtx new_reg, usage_insn; - rtx_insn *restore, *save; - bool after_p; - bool call_save_p; - machine_mode mode; - - if (original_regno < FIRST_PSEUDO_REGISTER) - { - rclass = ira_allocno_class_translate[REGNO_REG_CLASS (original_regno)]; - hard_regno = original_regno; - call_save_p = false; - nregs = 1; - mode = lra_reg_info[hard_regno].biggest_mode; - machine_mode reg_rtx_mode = GET_MODE (regno_reg_rtx[hard_regno]); - /* A reg can have a biggest_mode of VOIDmode if it was only ever seen as - part of a multi-word register. In that case, just use the reg_rtx - mode. Do the same also if the biggest mode was larger than a register - or we can not compare the modes. Otherwise, limit the size to that of - the biggest access in the function or to the natural mode at least. */ - if (mode == VOIDmode - || !ordered_p (GET_MODE_PRECISION (mode), - GET_MODE_PRECISION (reg_rtx_mode)) - || paradoxical_subreg_p (mode, reg_rtx_mode) - || maybe_gt (GET_MODE_PRECISION (reg_rtx_mode), GET_MODE_PRECISION (mode))) - { - original_reg = regno_reg_rtx[hard_regno]; - mode = reg_rtx_mode; - } - else - original_reg = gen_rtx_REG (mode, hard_regno); - } - else - { - mode = PSEUDO_REGNO_MODE (original_regno); - hard_regno = reg_renumber[original_regno]; - nregs = hard_regno_nregs (hard_regno, mode); - rclass = lra_get_allocno_class (original_regno); - original_reg = regno_reg_rtx[original_regno]; - call_save_p = need_for_call_save_p (original_regno); - } - lra_assert (hard_regno >= 0); - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " ((((((((((((((((((((((((((((((((((((((((((((((((\n"); - - if (call_save_p) - { - mode = HARD_REGNO_CALLER_SAVE_MODE (hard_regno, - hard_regno_nregs (hard_regno, mode), - mode); - new_reg = lra_create_new_reg (mode, NULL_RTX, NO_REGS, "save"); - } - else - { - rclass = choose_split_class (rclass, hard_regno, mode); - if (rclass == NO_REGS) - { - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, - " Rejecting split of %d(%s): " - "no good reg class for %d(%s)\n", - original_regno, - reg_class_names[lra_get_allocno_class (original_regno)], - hard_regno, - reg_class_names[REGNO_REG_CLASS (hard_regno)]); - fprintf - (lra_dump_file, - " ))))))))))))))))))))))))))))))))))))))))))))))))\n"); - } - return false; - } - /* Split_if_necessary can split hard registers used as part of a - multi-register mode but splits each register individually. The - mode used for each independent register may not be supported - so reject the split. Splitting the wider mode should theoretically - be possible but is not implemented. */ - if (!targetm.hard_regno_mode_ok (hard_regno, mode)) - { - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, - " Rejecting split of %d(%s): unsuitable mode %s\n", - original_regno, - reg_class_names[lra_get_allocno_class (original_regno)], - GET_MODE_NAME (mode)); - fprintf - (lra_dump_file, - " ))))))))))))))))))))))))))))))))))))))))))))))))\n"); - } - return false; - } - new_reg = lra_create_new_reg (mode, original_reg, rclass, "split"); - reg_renumber[REGNO (new_reg)] = hard_regno; - } - int new_regno = REGNO (new_reg); - save = emit_spill_move (true, new_reg, original_reg); - if (NEXT_INSN (save) != NULL_RTX && !call_save_p) - { - if (lra_dump_file != NULL) - { - fprintf - (lra_dump_file, - " Rejecting split %d->%d resulting in > 2 save insns:\n", - original_regno, new_regno); - dump_rtl_slim (lra_dump_file, save, NULL, -1, 0); - fprintf (lra_dump_file, - " ))))))))))))))))))))))))))))))))))))))))))))))))\n"); - } - return false; - } - restore = emit_spill_move (false, new_reg, original_reg); - if (NEXT_INSN (restore) != NULL_RTX && !call_save_p) - { - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, - " Rejecting split %d->%d " - "resulting in > 2 restore insns:\n", - original_regno, new_regno); - dump_rtl_slim (lra_dump_file, restore, NULL, -1, 0); - fprintf (lra_dump_file, - " ))))))))))))))))))))))))))))))))))))))))))))))))\n"); - } - return false; - } - /* Transfer equivalence information to the spill register, so that - if we fail to allocate the spill register, we have the option of - rematerializing the original value instead of spilling to the stack. */ - if (!HARD_REGISTER_NUM_P (original_regno) - && mode == PSEUDO_REGNO_MODE (original_regno)) - lra_copy_reg_equiv (new_regno, original_regno); - lra_reg_info[new_regno].restore_rtx = regno_reg_rtx[original_regno]; - bitmap_set_bit (&lra_split_regs, new_regno); - if (to != NULL) - { - lra_assert (next_usage_insns == NULL); - usage_insn = to; - after_p = TRUE; - } - else - { - /* We need check_only_regs only inside the inheritance pass. */ - bitmap_set_bit (&check_only_regs, new_regno); - bitmap_set_bit (&check_only_regs, original_regno); - after_p = usage_insns[original_regno].after_p; - for (;;) - { - if (GET_CODE (next_usage_insns) != INSN_LIST) - { - usage_insn = next_usage_insns; - break; - } - usage_insn = XEXP (next_usage_insns, 0); - lra_assert (DEBUG_INSN_P (usage_insn)); - next_usage_insns = XEXP (next_usage_insns, 1); - lra_substitute_pseudo (&usage_insn, original_regno, new_reg, false, - true); - lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn)); - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, " Split reuse change %d->%d:\n", - original_regno, new_regno); - dump_insn_slim (lra_dump_file, as_a <rtx_insn *> (usage_insn)); - } - } - } - lra_assert (NOTE_P (usage_insn) || NONDEBUG_INSN_P (usage_insn)); - lra_assert (usage_insn != insn || (after_p && before_p)); - lra_process_new_insns (as_a <rtx_insn *> (usage_insn), - after_p ? NULL : restore, - after_p ? restore : NULL, - call_save_p - ? "Add reg<-save" : "Add reg<-split"); - lra_process_new_insns (insn, before_p ? save : NULL, - before_p ? NULL : save, - call_save_p - ? "Add save<-reg" : "Add split<-reg"); - if (nregs > 1) - /* If we are trying to split multi-register. We should check - conflicts on the next assignment sub-pass. IRA can allocate on - sub-register levels, LRA do this on pseudos level right now and - this discrepancy may create allocation conflicts after - splitting. */ - check_and_force_assignment_correctness_p = true; - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " ))))))))))))))))))))))))))))))))))))))))))))))))\n"); - return true; -} - -/* Split a hard reg for reload pseudo REGNO having RCLASS and living - in the range [FROM, TO]. Return true if did a split. Otherwise, - return false. */ -bool -spill_hard_reg_in_range (int regno, enum reg_class rclass, rtx_insn *from, rtx_insn *to) -{ - int i, hard_regno; - int rclass_size; - rtx_insn *insn; - unsigned int uid; - bitmap_iterator bi; - HARD_REG_SET ignore; - - lra_assert (from != NULL && to != NULL); - CLEAR_HARD_REG_SET (ignore); - EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi) - { - lra_insn_recog_data_t id = lra_insn_recog_data[uid]; - struct lra_static_insn_data *static_id = id->insn_static_data; - struct lra_insn_reg *reg; - - for (reg = id->regs; reg != NULL; reg = reg->next) - if (reg->regno < FIRST_PSEUDO_REGISTER) - SET_HARD_REG_BIT (ignore, reg->regno); - for (reg = static_id->hard_regs; reg != NULL; reg = reg->next) - SET_HARD_REG_BIT (ignore, reg->regno); - } - rclass_size = ira_class_hard_regs_num[rclass]; - for (i = 0; i < rclass_size; i++) - { - hard_regno = ira_class_hard_regs[rclass][i]; - if (! TEST_HARD_REG_BIT (lra_reg_info[regno].conflict_hard_regs, hard_regno) - || TEST_HARD_REG_BIT (ignore, hard_regno)) - continue; - for (insn = from; insn != NEXT_INSN (to); insn = NEXT_INSN (insn)) - { - struct lra_static_insn_data *static_id; - struct lra_insn_reg *reg; - - if (!INSN_P (insn)) - continue; - if (bitmap_bit_p (&lra_reg_info[hard_regno].insn_bitmap, - INSN_UID (insn))) - break; - static_id = lra_get_insn_recog_data (insn)->insn_static_data; - for (reg = static_id->hard_regs; reg != NULL; reg = reg->next) - if (reg->regno == hard_regno) - break; - if (reg != NULL) - break; - } - if (insn != NEXT_INSN (to)) - continue; - if (split_reg (TRUE, hard_regno, from, NULL, to)) - return true; - } - return false; -} - -/* Recognize that we need a split transformation for insn INSN, which - defines or uses REGNO in its insn biggest MODE (we use it only if - REGNO is a hard register). POTENTIAL_RELOAD_HARD_REGS contains - hard registers which might be used for reloads since the EBB end. - Put the save before INSN if BEFORE_P is true. MAX_UID is maximla - uid before starting INSN processing. Return true if we succeed in - such transformation. */ -static bool -split_if_necessary (int regno, machine_mode mode, - HARD_REG_SET potential_reload_hard_regs, - bool before_p, rtx_insn *insn, int max_uid) -{ - bool res = false; - int i, nregs = 1; - rtx next_usage_insns; - - if (regno < FIRST_PSEUDO_REGISTER) - nregs = hard_regno_nregs (regno, mode); - for (i = 0; i < nregs; i++) - if (usage_insns[regno + i].check == curr_usage_insns_check - && (next_usage_insns = usage_insns[regno + i].insns) != NULL_RTX - /* To avoid processing the register twice or more. */ - && ((GET_CODE (next_usage_insns) != INSN_LIST - && INSN_UID (next_usage_insns) < max_uid) - || (GET_CODE (next_usage_insns) == INSN_LIST - && (INSN_UID (XEXP (next_usage_insns, 0)) < max_uid))) - && need_for_split_p (potential_reload_hard_regs, regno + i) - && split_reg (before_p, regno + i, insn, next_usage_insns, NULL)) - res = true; - return res; -} - -/* Return TRUE if rtx X is considered as an invariant for - inheritance. */ -static bool -invariant_p (const_rtx x) -{ - machine_mode mode; - const char *fmt; - enum rtx_code code; - int i, j; - - if (side_effects_p (x)) - return false; - - code = GET_CODE (x); - mode = GET_MODE (x); - if (code == SUBREG) - { - x = SUBREG_REG (x); - code = GET_CODE (x); - mode = wider_subreg_mode (mode, GET_MODE (x)); - } - - if (MEM_P (x)) - return false; - - if (REG_P (x)) - { - int i, nregs, regno = REGNO (x); - - if (regno >= FIRST_PSEUDO_REGISTER || regno == STACK_POINTER_REGNUM - || TEST_HARD_REG_BIT (eliminable_regset, regno) - || GET_MODE_CLASS (GET_MODE (x)) == MODE_CC) - return false; - nregs = hard_regno_nregs (regno, mode); - for (i = 0; i < nregs; i++) - if (! fixed_regs[regno + i] - /* A hard register may be clobbered in the current insn - but we can ignore this case because if the hard - register is used it should be set somewhere after the - clobber. */ - || bitmap_bit_p (&invalid_invariant_regs, regno + i)) - return false; - } - fmt = GET_RTX_FORMAT (code); - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - { - if (! invariant_p (XEXP (x, i))) - return false; - } - else if (fmt[i] == 'E') - { - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - if (! invariant_p (XVECEXP (x, i, j))) - return false; - } - } - return true; -} - -/* We have 'dest_reg <- invariant'. Let us try to make an invariant - inheritance transformation (using dest_reg instead invariant in a - subsequent insn). */ -static bool -process_invariant_for_inheritance (rtx dst_reg, rtx invariant_rtx) -{ - invariant_ptr_t invariant_ptr; - rtx_insn *insn, *new_insns; - rtx insn_set, insn_reg, new_reg; - int insn_regno; - bool succ_p = false; - int dst_regno = REGNO (dst_reg); - machine_mode dst_mode = GET_MODE (dst_reg); - enum reg_class cl = lra_get_allocno_class (dst_regno), insn_reg_cl; - - invariant_ptr = insert_invariant (invariant_rtx); - if ((insn = invariant_ptr->insn) != NULL_RTX) - { - /* We have a subsequent insn using the invariant. */ - insn_set = single_set (insn); - lra_assert (insn_set != NULL); - insn_reg = SET_DEST (insn_set); - lra_assert (REG_P (insn_reg)); - insn_regno = REGNO (insn_reg); - insn_reg_cl = lra_get_allocno_class (insn_regno); - - if (dst_mode == GET_MODE (insn_reg) - /* We should consider only result move reg insns which are - cheap. */ - && targetm.register_move_cost (dst_mode, cl, insn_reg_cl) == 2 - && targetm.register_move_cost (dst_mode, cl, cl) == 2) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - " [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\n"); - new_reg = lra_create_new_reg (dst_mode, dst_reg, - cl, "invariant inheritance"); - bitmap_set_bit (&lra_inheritance_pseudos, REGNO (new_reg)); - bitmap_set_bit (&check_only_regs, REGNO (new_reg)); - lra_reg_info[REGNO (new_reg)].restore_rtx = PATTERN (insn); - start_sequence (); - lra_emit_move (new_reg, dst_reg); - new_insns = get_insns (); - end_sequence (); - lra_process_new_insns (curr_insn, NULL, new_insns, - "Add invariant inheritance<-original"); - start_sequence (); - lra_emit_move (SET_DEST (insn_set), new_reg); - new_insns = get_insns (); - end_sequence (); - lra_process_new_insns (insn, NULL, new_insns, - "Changing reload<-inheritance"); - lra_set_insn_deleted (insn); - succ_p = true; - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, - " Invariant inheritance reuse change %d (bb%d):\n", - REGNO (new_reg), BLOCK_FOR_INSN (insn)->index); - dump_insn_slim (lra_dump_file, insn); - fprintf (lra_dump_file, - " ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\n"); - } - } - } - invariant_ptr->insn = curr_insn; - return succ_p; -} - -/* Check only registers living at the current program point in the - current EBB. */ -static bitmap_head live_regs; - -/* Update live info in EBB given by its HEAD and TAIL insns after - inheritance/split transformation. The function removes dead moves - too. */ -static void -update_ebb_live_info (rtx_insn *head, rtx_insn *tail) -{ - unsigned int j; - int i, regno; - bool live_p; - rtx_insn *prev_insn; - rtx set; - bool remove_p; - basic_block last_bb, prev_bb, curr_bb; - bitmap_iterator bi; - struct lra_insn_reg *reg; - edge e; - edge_iterator ei; - - last_bb = BLOCK_FOR_INSN (tail); - prev_bb = NULL; - for (curr_insn = tail; - curr_insn != PREV_INSN (head); - curr_insn = prev_insn) - { - prev_insn = PREV_INSN (curr_insn); - /* We need to process empty blocks too. They contain - NOTE_INSN_BASIC_BLOCK referring for the basic block. */ - if (NOTE_P (curr_insn) && NOTE_KIND (curr_insn) != NOTE_INSN_BASIC_BLOCK) - continue; - curr_bb = BLOCK_FOR_INSN (curr_insn); - if (curr_bb != prev_bb) - { - if (prev_bb != NULL) - { - /* Update df_get_live_in (prev_bb): */ - EXECUTE_IF_SET_IN_BITMAP (&check_only_regs, 0, j, bi) - if (bitmap_bit_p (&live_regs, j)) - bitmap_set_bit (df_get_live_in (prev_bb), j); - else - bitmap_clear_bit (df_get_live_in (prev_bb), j); - } - if (curr_bb != last_bb) - { - /* Update df_get_live_out (curr_bb): */ - EXECUTE_IF_SET_IN_BITMAP (&check_only_regs, 0, j, bi) - { - live_p = bitmap_bit_p (&live_regs, j); - if (! live_p) - FOR_EACH_EDGE (e, ei, curr_bb->succs) - if (bitmap_bit_p (df_get_live_in (e->dest), j)) - { - live_p = true; - break; - } - if (live_p) - bitmap_set_bit (df_get_live_out (curr_bb), j); - else - bitmap_clear_bit (df_get_live_out (curr_bb), j); - } - } - prev_bb = curr_bb; - bitmap_and (&live_regs, &check_only_regs, df_get_live_out (curr_bb)); - } - if (! NONDEBUG_INSN_P (curr_insn)) - continue; - curr_id = lra_get_insn_recog_data (curr_insn); - curr_static_id = curr_id->insn_static_data; - remove_p = false; - if ((set = single_set (curr_insn)) != NULL_RTX - && REG_P (SET_DEST (set)) - && (regno = REGNO (SET_DEST (set))) >= FIRST_PSEUDO_REGISTER - && SET_DEST (set) != pic_offset_table_rtx - && bitmap_bit_p (&check_only_regs, regno) - && ! bitmap_bit_p (&live_regs, regno)) - remove_p = true; - /* See which defined values die here. */ - for (reg = curr_id->regs; reg != NULL; reg = reg->next) - if (reg->type == OP_OUT && ! reg->subreg_p) - bitmap_clear_bit (&live_regs, reg->regno); - for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) - if (reg->type == OP_OUT && ! reg->subreg_p) - bitmap_clear_bit (&live_regs, reg->regno); - if (curr_id->arg_hard_regs != NULL) - /* Make clobbered argument hard registers die. */ - for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++) - if (regno >= FIRST_PSEUDO_REGISTER) - bitmap_clear_bit (&live_regs, regno - FIRST_PSEUDO_REGISTER); - /* Mark each used value as live. */ - for (reg = curr_id->regs; reg != NULL; reg = reg->next) - if (reg->type != OP_OUT - && bitmap_bit_p (&check_only_regs, reg->regno)) - bitmap_set_bit (&live_regs, reg->regno); - for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) - if (reg->type != OP_OUT - && bitmap_bit_p (&check_only_regs, reg->regno)) - bitmap_set_bit (&live_regs, reg->regno); - if (curr_id->arg_hard_regs != NULL) - /* Make used argument hard registers live. */ - for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++) - if (regno < FIRST_PSEUDO_REGISTER - && bitmap_bit_p (&check_only_regs, regno)) - bitmap_set_bit (&live_regs, regno); - /* It is quite important to remove dead move insns because it - means removing dead store. We don't need to process them for - constraints. */ - if (remove_p) - { - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, " Removing dead insn:\n "); - dump_insn_slim (lra_dump_file, curr_insn); - } - lra_set_insn_deleted (curr_insn); - } - } -} - -/* The structure describes info to do an inheritance for the current - insn. We need to collect such info first before doing the - transformations because the transformations change the insn - internal representation. */ -struct to_inherit -{ - /* Original regno. */ - int regno; - /* Subsequent insns which can inherit original reg value. */ - rtx insns; -}; - -/* Array containing all info for doing inheritance from the current - insn. */ -static struct to_inherit to_inherit[LRA_MAX_INSN_RELOADS]; - -/* Number elements in the previous array. */ -static int to_inherit_num; - -/* Add inheritance info REGNO and INSNS. Their meaning is described in - structure to_inherit. */ -static void -add_to_inherit (int regno, rtx insns) -{ - int i; - - for (i = 0; i < to_inherit_num; i++) - if (to_inherit[i].regno == regno) - return; - lra_assert (to_inherit_num < LRA_MAX_INSN_RELOADS); - to_inherit[to_inherit_num].regno = regno; - to_inherit[to_inherit_num++].insns = insns; -} - -/* Return the last non-debug insn in basic block BB, or the block begin - note if none. */ -static rtx_insn * -get_last_insertion_point (basic_block bb) -{ - rtx_insn *insn; - - FOR_BB_INSNS_REVERSE (bb, insn) - if (NONDEBUG_INSN_P (insn) || NOTE_INSN_BASIC_BLOCK_P (insn)) - return insn; - gcc_unreachable (); -} - -/* Set up RES by registers living on edges FROM except the edge (FROM, - TO) or by registers set up in a jump insn in BB FROM. */ -static void -get_live_on_other_edges (basic_block from, basic_block to, bitmap res) -{ - rtx_insn *last; - struct lra_insn_reg *reg; - edge e; - edge_iterator ei; - - lra_assert (to != NULL); - bitmap_clear (res); - FOR_EACH_EDGE (e, ei, from->succs) - if (e->dest != to) - bitmap_ior_into (res, df_get_live_in (e->dest)); - last = get_last_insertion_point (from); - if (! JUMP_P (last)) - return; - curr_id = lra_get_insn_recog_data (last); - for (reg = curr_id->regs; reg != NULL; reg = reg->next) - if (reg->type != OP_IN) - bitmap_set_bit (res, reg->regno); -} - -/* Used as a temporary results of some bitmap calculations. */ -static bitmap_head temp_bitmap; - -/* We split for reloads of small class of hard regs. The following - defines how many hard regs the class should have to be qualified as - small. The code is mostly oriented to x86/x86-64 architecture - where some insns need to use only specific register or pair of - registers and these register can live in RTL explicitly, e.g. for - parameter passing. */ -static const int max_small_class_regs_num = 2; - -/* Do inheritance/split transformations in EBB starting with HEAD and - finishing on TAIL. We process EBB insns in the reverse order. - Return true if we did any inheritance/split transformation in the - EBB. - - We should avoid excessive splitting which results in worse code - because of inaccurate cost calculations for spilling new split - pseudos in such case. To achieve this we do splitting only if - register pressure is high in given basic block and there are reload - pseudos requiring hard registers. We could do more register - pressure calculations at any given program point to avoid necessary - splitting even more but it is to expensive and the current approach - works well enough. */ -static bool -inherit_in_ebb (rtx_insn *head, rtx_insn *tail) -{ - int i, src_regno, dst_regno, nregs; - bool change_p, succ_p, update_reloads_num_p; - rtx_insn *prev_insn, *last_insn; - rtx next_usage_insns, curr_set; - enum reg_class cl; - struct lra_insn_reg *reg; - basic_block last_processed_bb, curr_bb = NULL; - HARD_REG_SET potential_reload_hard_regs, live_hard_regs; - bitmap to_process; - unsigned int j; - bitmap_iterator bi; - bool head_p, after_p; - - change_p = false; - curr_usage_insns_check++; - clear_invariants (); - reloads_num = calls_num = 0; - for (unsigned int i = 0; i < NUM_ABI_IDS; ++i) - last_call_for_abi[i] = 0; - CLEAR_HARD_REG_SET (full_and_partial_call_clobbers); - bitmap_clear (&check_only_regs); - bitmap_clear (&invalid_invariant_regs); - last_processed_bb = NULL; - CLEAR_HARD_REG_SET (potential_reload_hard_regs); - live_hard_regs = eliminable_regset | lra_no_alloc_regs; - /* We don't process new insns generated in the loop. */ - for (curr_insn = tail; curr_insn != PREV_INSN (head); curr_insn = prev_insn) - { - prev_insn = PREV_INSN (curr_insn); - if (BLOCK_FOR_INSN (curr_insn) != NULL) - curr_bb = BLOCK_FOR_INSN (curr_insn); - if (last_processed_bb != curr_bb) - { - /* We are at the end of BB. Add qualified living - pseudos for potential splitting. */ - to_process = df_get_live_out (curr_bb); - if (last_processed_bb != NULL) - { - /* We are somewhere in the middle of EBB. */ - get_live_on_other_edges (curr_bb, last_processed_bb, - &temp_bitmap); - to_process = &temp_bitmap; - } - last_processed_bb = curr_bb; - last_insn = get_last_insertion_point (curr_bb); - after_p = (! JUMP_P (last_insn) - && (! CALL_P (last_insn) - || (find_reg_note (last_insn, - REG_NORETURN, NULL_RTX) == NULL_RTX - && ! SIBLING_CALL_P (last_insn)))); - CLEAR_HARD_REG_SET (potential_reload_hard_regs); - EXECUTE_IF_SET_IN_BITMAP (to_process, 0, j, bi) - { - if ((int) j >= lra_constraint_new_regno_start) - break; - if (j < FIRST_PSEUDO_REGISTER || reg_renumber[j] >= 0) - { - if (j < FIRST_PSEUDO_REGISTER) - SET_HARD_REG_BIT (live_hard_regs, j); - else - add_to_hard_reg_set (&live_hard_regs, - PSEUDO_REGNO_MODE (j), - reg_renumber[j]); - setup_next_usage_insn (j, last_insn, reloads_num, after_p); - } - } - } - src_regno = dst_regno = -1; - curr_set = single_set (curr_insn); - if (curr_set != NULL_RTX && REG_P (SET_DEST (curr_set))) - dst_regno = REGNO (SET_DEST (curr_set)); - if (curr_set != NULL_RTX && REG_P (SET_SRC (curr_set))) - src_regno = REGNO (SET_SRC (curr_set)); - update_reloads_num_p = true; - if (src_regno < lra_constraint_new_regno_start - && src_regno >= FIRST_PSEUDO_REGISTER - && reg_renumber[src_regno] < 0 - && dst_regno >= lra_constraint_new_regno_start - && (cl = lra_get_allocno_class (dst_regno)) != NO_REGS) - { - /* 'reload_pseudo <- original_pseudo'. */ - if (ira_class_hard_regs_num[cl] <= max_small_class_regs_num) - reloads_num++; - update_reloads_num_p = false; - succ_p = false; - if (usage_insns[src_regno].check == curr_usage_insns_check - && (next_usage_insns = usage_insns[src_regno].insns) != NULL_RTX) - succ_p = inherit_reload_reg (false, src_regno, cl, - curr_insn, next_usage_insns); - if (succ_p) - change_p = true; - else - setup_next_usage_insn (src_regno, curr_insn, reloads_num, false); - if (hard_reg_set_subset_p (reg_class_contents[cl], live_hard_regs)) - potential_reload_hard_regs |= reg_class_contents[cl]; - } - else if (src_regno < 0 - && dst_regno >= lra_constraint_new_regno_start - && invariant_p (SET_SRC (curr_set)) - && (cl = lra_get_allocno_class (dst_regno)) != NO_REGS - && ! bitmap_bit_p (&invalid_invariant_regs, dst_regno) - && ! bitmap_bit_p (&invalid_invariant_regs, - ORIGINAL_REGNO(regno_reg_rtx[dst_regno]))) - { - /* 'reload_pseudo <- invariant'. */ - if (ira_class_hard_regs_num[cl] <= max_small_class_regs_num) - reloads_num++; - update_reloads_num_p = false; - if (process_invariant_for_inheritance (SET_DEST (curr_set), SET_SRC (curr_set))) - change_p = true; - if (hard_reg_set_subset_p (reg_class_contents[cl], live_hard_regs)) - potential_reload_hard_regs |= reg_class_contents[cl]; - } - else if (src_regno >= lra_constraint_new_regno_start - && dst_regno < lra_constraint_new_regno_start - && dst_regno >= FIRST_PSEUDO_REGISTER - && reg_renumber[dst_regno] < 0 - && (cl = lra_get_allocno_class (src_regno)) != NO_REGS - && usage_insns[dst_regno].check == curr_usage_insns_check - && (next_usage_insns - = usage_insns[dst_regno].insns) != NULL_RTX) - { - if (ira_class_hard_regs_num[cl] <= max_small_class_regs_num) - reloads_num++; - update_reloads_num_p = false; - /* 'original_pseudo <- reload_pseudo'. */ - if (! JUMP_P (curr_insn) - && inherit_reload_reg (true, dst_regno, cl, - curr_insn, next_usage_insns)) - change_p = true; - /* Invalidate. */ - usage_insns[dst_regno].check = 0; - if (hard_reg_set_subset_p (reg_class_contents[cl], live_hard_regs)) - potential_reload_hard_regs |= reg_class_contents[cl]; - } - else if (INSN_P (curr_insn)) - { - int iter; - int max_uid = get_max_uid (); - - curr_id = lra_get_insn_recog_data (curr_insn); - curr_static_id = curr_id->insn_static_data; - to_inherit_num = 0; - /* Process insn definitions. */ - for (iter = 0; iter < 2; iter++) - for (reg = iter == 0 ? curr_id->regs : curr_static_id->hard_regs; - reg != NULL; - reg = reg->next) - if (reg->type != OP_IN - && (dst_regno = reg->regno) < lra_constraint_new_regno_start) - { - if (dst_regno >= FIRST_PSEUDO_REGISTER && reg->type == OP_OUT - && reg_renumber[dst_regno] < 0 && ! reg->subreg_p - && usage_insns[dst_regno].check == curr_usage_insns_check - && (next_usage_insns - = usage_insns[dst_regno].insns) != NULL_RTX) - { - struct lra_insn_reg *r; - - for (r = curr_id->regs; r != NULL; r = r->next) - if (r->type != OP_OUT && r->regno == dst_regno) - break; - /* Don't do inheritance if the pseudo is also - used in the insn. */ - if (r == NULL) - /* We cannot do inheritance right now - because the current insn reg info (chain - regs) can change after that. */ - add_to_inherit (dst_regno, next_usage_insns); - } - /* We cannot process one reg twice here because of - usage_insns invalidation. */ - if ((dst_regno < FIRST_PSEUDO_REGISTER - || reg_renumber[dst_regno] >= 0) - && ! reg->subreg_p && reg->type != OP_IN) - { - HARD_REG_SET s; - - if (split_if_necessary (dst_regno, reg->biggest_mode, - potential_reload_hard_regs, - false, curr_insn, max_uid)) - change_p = true; - CLEAR_HARD_REG_SET (s); - if (dst_regno < FIRST_PSEUDO_REGISTER) - add_to_hard_reg_set (&s, reg->biggest_mode, dst_regno); - else - add_to_hard_reg_set (&s, PSEUDO_REGNO_MODE (dst_regno), - reg_renumber[dst_regno]); - live_hard_regs &= ~s; - potential_reload_hard_regs &= ~s; - } - /* We should invalidate potential inheritance or - splitting for the current insn usages to the next - usage insns (see code below) as the output pseudo - prevents this. */ - if ((dst_regno >= FIRST_PSEUDO_REGISTER - && reg_renumber[dst_regno] < 0) - || (reg->type == OP_OUT && ! reg->subreg_p - && (dst_regno < FIRST_PSEUDO_REGISTER - || reg_renumber[dst_regno] >= 0))) - { - /* Invalidate and mark definitions. */ - if (dst_regno >= FIRST_PSEUDO_REGISTER) - usage_insns[dst_regno].check = -(int) INSN_UID (curr_insn); - else - { - nregs = hard_regno_nregs (dst_regno, - reg->biggest_mode); - for (i = 0; i < nregs; i++) - usage_insns[dst_regno + i].check - = -(int) INSN_UID (curr_insn); - } - } - } - /* Process clobbered call regs. */ - if (curr_id->arg_hard_regs != NULL) - for (i = 0; (dst_regno = curr_id->arg_hard_regs[i]) >= 0; i++) - if (dst_regno >= FIRST_PSEUDO_REGISTER) - usage_insns[dst_regno - FIRST_PSEUDO_REGISTER].check - = -(int) INSN_UID (curr_insn); - if (! JUMP_P (curr_insn)) - for (i = 0; i < to_inherit_num; i++) - if (inherit_reload_reg (true, to_inherit[i].regno, - ALL_REGS, curr_insn, - to_inherit[i].insns)) - change_p = true; - if (CALL_P (curr_insn)) - { - rtx cheap, pat, dest; - rtx_insn *restore; - int regno, hard_regno; - - calls_num++; - function_abi callee_abi = insn_callee_abi (curr_insn); - last_call_for_abi[callee_abi.id ()] = calls_num; - full_and_partial_call_clobbers - |= callee_abi.full_and_partial_reg_clobbers (); - if ((cheap = find_reg_note (curr_insn, - REG_RETURNED, NULL_RTX)) != NULL_RTX - && ((cheap = XEXP (cheap, 0)), true) - && (regno = REGNO (cheap)) >= FIRST_PSEUDO_REGISTER - && (hard_regno = reg_renumber[regno]) >= 0 - && usage_insns[regno].check == curr_usage_insns_check - /* If there are pending saves/restores, the - optimization is not worth. */ - && usage_insns[regno].calls_num == calls_num - 1 - && callee_abi.clobbers_reg_p (GET_MODE (cheap), hard_regno)) - { - /* Restore the pseudo from the call result as - REG_RETURNED note says that the pseudo value is - in the call result and the pseudo is an argument - of the call. */ - pat = PATTERN (curr_insn); - if (GET_CODE (pat) == PARALLEL) - pat = XVECEXP (pat, 0, 0); - dest = SET_DEST (pat); - /* For multiple return values dest is PARALLEL. - Currently we handle only single return value case. */ - if (REG_P (dest)) - { - start_sequence (); - emit_move_insn (cheap, copy_rtx (dest)); - restore = get_insns (); - end_sequence (); - lra_process_new_insns (curr_insn, NULL, restore, - "Inserting call parameter restore"); - /* We don't need to save/restore of the pseudo from - this call. */ - usage_insns[regno].calls_num = calls_num; - remove_from_hard_reg_set - (&full_and_partial_call_clobbers, - GET_MODE (cheap), hard_regno); - bitmap_set_bit (&check_only_regs, regno); - } - } - } - to_inherit_num = 0; - /* Process insn usages. */ - for (iter = 0; iter < 2; iter++) - for (reg = iter == 0 ? curr_id->regs : curr_static_id->hard_regs; - reg != NULL; - reg = reg->next) - if ((reg->type != OP_OUT - || (reg->type == OP_OUT && reg->subreg_p)) - && (src_regno = reg->regno) < lra_constraint_new_regno_start) - { - if (src_regno >= FIRST_PSEUDO_REGISTER - && reg_renumber[src_regno] < 0 && reg->type == OP_IN) - { - if (usage_insns[src_regno].check == curr_usage_insns_check - && (next_usage_insns - = usage_insns[src_regno].insns) != NULL_RTX - && NONDEBUG_INSN_P (curr_insn)) - add_to_inherit (src_regno, next_usage_insns); - else if (usage_insns[src_regno].check - != -(int) INSN_UID (curr_insn)) - /* Add usages but only if the reg is not set up - in the same insn. */ - add_next_usage_insn (src_regno, curr_insn, reloads_num); - } - else if (src_regno < FIRST_PSEUDO_REGISTER - || reg_renumber[src_regno] >= 0) - { - bool before_p; - rtx_insn *use_insn = curr_insn; - - before_p = (JUMP_P (curr_insn) - || (CALL_P (curr_insn) && reg->type == OP_IN)); - if (NONDEBUG_INSN_P (curr_insn) - && (! JUMP_P (curr_insn) || reg->type == OP_IN) - && split_if_necessary (src_regno, reg->biggest_mode, - potential_reload_hard_regs, - before_p, curr_insn, max_uid)) - { - if (reg->subreg_p) - check_and_force_assignment_correctness_p = true; - change_p = true; - /* Invalidate. */ - usage_insns[src_regno].check = 0; - if (before_p) - use_insn = PREV_INSN (curr_insn); - } - if (NONDEBUG_INSN_P (curr_insn)) - { - if (src_regno < FIRST_PSEUDO_REGISTER) - add_to_hard_reg_set (&live_hard_regs, - reg->biggest_mode, src_regno); - else - add_to_hard_reg_set (&live_hard_regs, - PSEUDO_REGNO_MODE (src_regno), - reg_renumber[src_regno]); - } - if (src_regno >= FIRST_PSEUDO_REGISTER) - add_next_usage_insn (src_regno, use_insn, reloads_num); - else - { - for (i = 0; i < hard_regno_nregs (src_regno, reg->biggest_mode); i++) - add_next_usage_insn (src_regno + i, use_insn, reloads_num); - } - } - } - /* Process used call regs. */ - if (curr_id->arg_hard_regs != NULL) - for (i = 0; (src_regno = curr_id->arg_hard_regs[i]) >= 0; i++) - if (src_regno < FIRST_PSEUDO_REGISTER) - { - SET_HARD_REG_BIT (live_hard_regs, src_regno); - add_next_usage_insn (src_regno, curr_insn, reloads_num); - } - for (i = 0; i < to_inherit_num; i++) - { - src_regno = to_inherit[i].regno; - if (inherit_reload_reg (false, src_regno, ALL_REGS, - curr_insn, to_inherit[i].insns)) - change_p = true; - else - setup_next_usage_insn (src_regno, curr_insn, reloads_num, false); - } - } - if (update_reloads_num_p - && NONDEBUG_INSN_P (curr_insn) && curr_set != NULL_RTX) - { - int regno = -1; - if ((REG_P (SET_DEST (curr_set)) - && (regno = REGNO (SET_DEST (curr_set))) >= lra_constraint_new_regno_start - && reg_renumber[regno] < 0 - && (cl = lra_get_allocno_class (regno)) != NO_REGS) - || (REG_P (SET_SRC (curr_set)) - && (regno = REGNO (SET_SRC (curr_set))) >= lra_constraint_new_regno_start - && reg_renumber[regno] < 0 - && (cl = lra_get_allocno_class (regno)) != NO_REGS)) - { - if (ira_class_hard_regs_num[cl] <= max_small_class_regs_num) - reloads_num++; - if (hard_reg_set_subset_p (reg_class_contents[cl], live_hard_regs)) - potential_reload_hard_regs |= reg_class_contents[cl]; - } - } - if (NONDEBUG_INSN_P (curr_insn)) - { - int regno; - - /* Invalidate invariants with changed regs. */ - curr_id = lra_get_insn_recog_data (curr_insn); - for (reg = curr_id->regs; reg != NULL; reg = reg->next) - if (reg->type != OP_IN) - { - bitmap_set_bit (&invalid_invariant_regs, reg->regno); - bitmap_set_bit (&invalid_invariant_regs, - ORIGINAL_REGNO (regno_reg_rtx[reg->regno])); - } - curr_static_id = curr_id->insn_static_data; - for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) - if (reg->type != OP_IN) - bitmap_set_bit (&invalid_invariant_regs, reg->regno); - if (curr_id->arg_hard_regs != NULL) - for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++) - if (regno >= FIRST_PSEUDO_REGISTER) - bitmap_set_bit (&invalid_invariant_regs, - regno - FIRST_PSEUDO_REGISTER); - } - /* We reached the start of the current basic block. */ - if (prev_insn == NULL_RTX || prev_insn == PREV_INSN (head) - || BLOCK_FOR_INSN (prev_insn) != curr_bb) - { - /* We reached the beginning of the current block -- do - rest of spliting in the current BB. */ - to_process = df_get_live_in (curr_bb); - if (BLOCK_FOR_INSN (head) != curr_bb) - { - /* We are somewhere in the middle of EBB. */ - get_live_on_other_edges (EDGE_PRED (curr_bb, 0)->src, - curr_bb, &temp_bitmap); - to_process = &temp_bitmap; - } - head_p = true; - EXECUTE_IF_SET_IN_BITMAP (to_process, 0, j, bi) - { - if ((int) j >= lra_constraint_new_regno_start) - break; - if (((int) j < FIRST_PSEUDO_REGISTER || reg_renumber[j] >= 0) - && usage_insns[j].check == curr_usage_insns_check - && (next_usage_insns = usage_insns[j].insns) != NULL_RTX) - { - if (need_for_split_p (potential_reload_hard_regs, j)) - { - if (lra_dump_file != NULL && head_p) - { - fprintf (lra_dump_file, - " ----------------------------------\n"); - head_p = false; - } - if (split_reg (false, j, bb_note (curr_bb), - next_usage_insns, NULL)) - change_p = true; - } - usage_insns[j].check = 0; - } - } - } - } - return change_p; -} - -/* This value affects EBB forming. If probability of edge from EBB to - a BB is not greater than the following value, we don't add the BB - to EBB. */ -#define EBB_PROBABILITY_CUTOFF \ - ((REG_BR_PROB_BASE * param_lra_inheritance_ebb_probability_cutoff) / 100) - -/* Current number of inheritance/split iteration. */ -int lra_inheritance_iter; - -/* Entry function for inheritance/split pass. */ -void -lra_inheritance (void) -{ - int i; - basic_block bb, start_bb; - edge e; - - lra_inheritance_iter++; - if (lra_inheritance_iter > LRA_MAX_INHERITANCE_PASSES) - return; - timevar_push (TV_LRA_INHERITANCE); - if (lra_dump_file != NULL) - fprintf (lra_dump_file, "\n********** Inheritance #%d: **********\n\n", - lra_inheritance_iter); - curr_usage_insns_check = 0; - usage_insns = XNEWVEC (struct usage_insns, lra_constraint_new_regno_start); - for (i = 0; i < lra_constraint_new_regno_start; i++) - usage_insns[i].check = 0; - bitmap_initialize (&check_only_regs, ®_obstack); - bitmap_initialize (&invalid_invariant_regs, ®_obstack); - bitmap_initialize (&live_regs, ®_obstack); - bitmap_initialize (&temp_bitmap, ®_obstack); - bitmap_initialize (&ebb_global_regs, ®_obstack); - FOR_EACH_BB_FN (bb, cfun) - { - start_bb = bb; - if (lra_dump_file != NULL) - fprintf (lra_dump_file, "EBB"); - /* Form a EBB starting with BB. */ - bitmap_clear (&ebb_global_regs); - bitmap_ior_into (&ebb_global_regs, df_get_live_in (bb)); - for (;;) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, " %d", bb->index); - if (bb->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun) - || LABEL_P (BB_HEAD (bb->next_bb))) - break; - e = find_fallthru_edge (bb->succs); - if (! e) - break; - if (e->probability.initialized_p () - && e->probability.to_reg_br_prob_base () < EBB_PROBABILITY_CUTOFF) - break; - bb = bb->next_bb; - } - bitmap_ior_into (&ebb_global_regs, df_get_live_out (bb)); - if (lra_dump_file != NULL) - fprintf (lra_dump_file, "\n"); - if (inherit_in_ebb (BB_HEAD (start_bb), BB_END (bb))) - /* Remember that the EBB head and tail can change in - inherit_in_ebb. */ - update_ebb_live_info (BB_HEAD (start_bb), BB_END (bb)); - } - bitmap_release (&ebb_global_regs); - bitmap_release (&temp_bitmap); - bitmap_release (&live_regs); - bitmap_release (&invalid_invariant_regs); - bitmap_release (&check_only_regs); - free (usage_insns); - - timevar_pop (TV_LRA_INHERITANCE); -} - - - -/* This page contains code to undo failed inheritance/split - transformations. */ - -/* Current number of iteration undoing inheritance/split. */ -int lra_undo_inheritance_iter; - -/* Fix BB live info LIVE after removing pseudos created on pass doing - inheritance/split which are REMOVED_PSEUDOS. */ -static void -fix_bb_live_info (bitmap live, bitmap removed_pseudos) -{ - unsigned int regno; - bitmap_iterator bi; - - EXECUTE_IF_SET_IN_BITMAP (removed_pseudos, 0, regno, bi) - if (bitmap_clear_bit (live, regno) - && REG_P (lra_reg_info[regno].restore_rtx)) - bitmap_set_bit (live, REGNO (lra_reg_info[regno].restore_rtx)); -} - -/* Return regno of the (subreg of) REG. Otherwise, return a negative - number. */ -static int -get_regno (rtx reg) -{ - if (GET_CODE (reg) == SUBREG) - reg = SUBREG_REG (reg); - if (REG_P (reg)) - return REGNO (reg); - return -1; -} - -/* Delete a move INSN with destination reg DREGNO and a previous - clobber insn with the same regno. The inheritance/split code can - generate moves with preceding clobber and when we delete such moves - we should delete the clobber insn too to keep the correct life - info. */ -static void -delete_move_and_clobber (rtx_insn *insn, int dregno) -{ - rtx_insn *prev_insn = PREV_INSN (insn); - - lra_set_insn_deleted (insn); - lra_assert (dregno >= 0); - if (prev_insn != NULL && NONDEBUG_INSN_P (prev_insn) - && GET_CODE (PATTERN (prev_insn)) == CLOBBER - && dregno == get_regno (XEXP (PATTERN (prev_insn), 0))) - lra_set_insn_deleted (prev_insn); -} - -/* Remove inheritance/split pseudos which are in REMOVE_PSEUDOS and - return true if we did any change. The undo transformations for - inheritance looks like - i <- i2 - p <- i => p <- i2 - or removing - p <- i, i <- p, and i <- i3 - where p is original pseudo from which inheritance pseudo i was - created, i and i3 are removed inheritance pseudos, i2 is another - not removed inheritance pseudo. All split pseudos or other - occurrences of removed inheritance pseudos are changed on the - corresponding original pseudos. - - The function also schedules insns changed and created during - inheritance/split pass for processing by the subsequent constraint - pass. */ -static bool -remove_inheritance_pseudos (bitmap remove_pseudos) -{ - basic_block bb; - int regno, sregno, prev_sregno, dregno; - rtx restore_rtx; - rtx set, prev_set; - rtx_insn *prev_insn; - bool change_p, done_p; - - change_p = ! bitmap_empty_p (remove_pseudos); - /* We cannot finish the function right away if CHANGE_P is true - because we need to marks insns affected by previous - inheritance/split pass for processing by the subsequent - constraint pass. */ - FOR_EACH_BB_FN (bb, cfun) - { - fix_bb_live_info (df_get_live_in (bb), remove_pseudos); - fix_bb_live_info (df_get_live_out (bb), remove_pseudos); - FOR_BB_INSNS_REVERSE (bb, curr_insn) - { - if (! INSN_P (curr_insn)) - continue; - done_p = false; - sregno = dregno = -1; - if (change_p && NONDEBUG_INSN_P (curr_insn) - && (set = single_set (curr_insn)) != NULL_RTX) - { - dregno = get_regno (SET_DEST (set)); - sregno = get_regno (SET_SRC (set)); - } - - if (sregno >= 0 && dregno >= 0) - { - if (bitmap_bit_p (remove_pseudos, dregno) - && ! REG_P (lra_reg_info[dregno].restore_rtx)) - { - /* invariant inheritance pseudo <- original pseudo */ - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, " Removing invariant inheritance:\n"); - dump_insn_slim (lra_dump_file, curr_insn); - fprintf (lra_dump_file, "\n"); - } - delete_move_and_clobber (curr_insn, dregno); - done_p = true; - } - else if (bitmap_bit_p (remove_pseudos, sregno) - && ! REG_P (lra_reg_info[sregno].restore_rtx)) - { - /* reload pseudo <- invariant inheritance pseudo */ - start_sequence (); - /* We cannot just change the source. It might be - an insn different from the move. */ - emit_insn (lra_reg_info[sregno].restore_rtx); - rtx_insn *new_insns = get_insns (); - end_sequence (); - lra_assert (single_set (new_insns) != NULL - && SET_DEST (set) == SET_DEST (single_set (new_insns))); - lra_process_new_insns (curr_insn, NULL, new_insns, - "Changing reload<-invariant inheritance"); - delete_move_and_clobber (curr_insn, dregno); - done_p = true; - } - else if ((bitmap_bit_p (remove_pseudos, sregno) - && (get_regno (lra_reg_info[sregno].restore_rtx) == dregno - || (bitmap_bit_p (remove_pseudos, dregno) - && get_regno (lra_reg_info[sregno].restore_rtx) >= 0 - && (get_regno (lra_reg_info[sregno].restore_rtx) - == get_regno (lra_reg_info[dregno].restore_rtx))))) - || (bitmap_bit_p (remove_pseudos, dregno) - && get_regno (lra_reg_info[dregno].restore_rtx) == sregno)) - /* One of the following cases: - original <- removed inheritance pseudo - removed inherit pseudo <- another removed inherit pseudo - removed inherit pseudo <- original pseudo - Or - removed_split_pseudo <- original_reg - original_reg <- removed_split_pseudo */ - { - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, " Removing %s:\n", - bitmap_bit_p (&lra_split_regs, sregno) - || bitmap_bit_p (&lra_split_regs, dregno) - ? "split" : "inheritance"); - dump_insn_slim (lra_dump_file, curr_insn); - } - delete_move_and_clobber (curr_insn, dregno); - done_p = true; - } - else if (bitmap_bit_p (remove_pseudos, sregno) - && bitmap_bit_p (&lra_inheritance_pseudos, sregno)) - { - /* Search the following pattern: - inherit_or_split_pseudo1 <- inherit_or_split_pseudo2 - original_pseudo <- inherit_or_split_pseudo1 - where the 2nd insn is the current insn and - inherit_or_split_pseudo2 is not removed. If it is found, - change the current insn onto: - original_pseudo <- inherit_or_split_pseudo2. */ - for (prev_insn = PREV_INSN (curr_insn); - prev_insn != NULL_RTX && ! NONDEBUG_INSN_P (prev_insn); - prev_insn = PREV_INSN (prev_insn)) - ; - if (prev_insn != NULL_RTX && BLOCK_FOR_INSN (prev_insn) == bb - && (prev_set = single_set (prev_insn)) != NULL_RTX - /* There should be no subregs in insn we are - searching because only the original reg might - be in subreg when we changed the mode of - load/store for splitting. */ - && REG_P (SET_DEST (prev_set)) - && REG_P (SET_SRC (prev_set)) - && (int) REGNO (SET_DEST (prev_set)) == sregno - && ((prev_sregno = REGNO (SET_SRC (prev_set))) - >= FIRST_PSEUDO_REGISTER) - && (lra_reg_info[prev_sregno].restore_rtx == NULL_RTX - || - /* As we consider chain of inheritance or - splitting described in above comment we should - check that sregno and prev_sregno were - inheritance/split pseudos created from the - same original regno. */ - (get_regno (lra_reg_info[sregno].restore_rtx) >= 0 - && (get_regno (lra_reg_info[sregno].restore_rtx) - == get_regno (lra_reg_info[prev_sregno].restore_rtx)))) - && ! bitmap_bit_p (remove_pseudos, prev_sregno)) - { - lra_assert (GET_MODE (SET_SRC (prev_set)) - == GET_MODE (regno_reg_rtx[sregno])); - /* Although we have a single set, the insn can - contain more one sregno register occurrence - as a source. Change all occurrences. */ - lra_substitute_pseudo_within_insn (curr_insn, sregno, - SET_SRC (prev_set), - false); - /* As we are finishing with processing the insn - here, check the destination too as it might - inheritance pseudo for another pseudo. */ - if (bitmap_bit_p (remove_pseudos, dregno) - && bitmap_bit_p (&lra_inheritance_pseudos, dregno) - && (restore_rtx - = lra_reg_info[dregno].restore_rtx) != NULL_RTX) - { - if (GET_CODE (SET_DEST (set)) == SUBREG) - SUBREG_REG (SET_DEST (set)) = restore_rtx; - else - SET_DEST (set) = restore_rtx; - } - lra_push_insn_and_update_insn_regno_info (curr_insn); - lra_set_used_insn_alternative_by_uid - (INSN_UID (curr_insn), LRA_UNKNOWN_ALT); - done_p = true; - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, " Change reload insn:\n"); - dump_insn_slim (lra_dump_file, curr_insn); - } - } - } - } - if (! done_p) - { - struct lra_insn_reg *reg; - bool restored_regs_p = false; - bool kept_regs_p = false; - - curr_id = lra_get_insn_recog_data (curr_insn); - for (reg = curr_id->regs; reg != NULL; reg = reg->next) - { - regno = reg->regno; - restore_rtx = lra_reg_info[regno].restore_rtx; - if (restore_rtx != NULL_RTX) - { - if (change_p && bitmap_bit_p (remove_pseudos, regno)) - { - lra_substitute_pseudo_within_insn - (curr_insn, regno, restore_rtx, false); - restored_regs_p = true; - } - else - kept_regs_p = true; - } - } - if (NONDEBUG_INSN_P (curr_insn) && kept_regs_p) - { - /* The instruction has changed since the previous - constraints pass. */ - lra_push_insn_and_update_insn_regno_info (curr_insn); - lra_set_used_insn_alternative_by_uid - (INSN_UID (curr_insn), LRA_UNKNOWN_ALT); - } - else if (restored_regs_p) - /* The instruction has been restored to the form that - it had during the previous constraints pass. */ - lra_update_insn_regno_info (curr_insn); - if (restored_regs_p && lra_dump_file != NULL) - { - fprintf (lra_dump_file, " Insn after restoring regs:\n"); - dump_insn_slim (lra_dump_file, curr_insn); - } - } - } - } - return change_p; -} - -/* If optional reload pseudos failed to get a hard register or was not - inherited, it is better to remove optional reloads. We do this - transformation after undoing inheritance to figure out necessity to - remove optional reloads easier. Return true if we do any - change. */ -static bool -undo_optional_reloads (void) -{ - bool change_p, keep_p; - unsigned int regno, uid; - bitmap_iterator bi, bi2; - rtx_insn *insn; - rtx set, src, dest; - auto_bitmap removed_optional_reload_pseudos (®_obstack); - - bitmap_copy (removed_optional_reload_pseudos, &lra_optional_reload_pseudos); - EXECUTE_IF_SET_IN_BITMAP (&lra_optional_reload_pseudos, 0, regno, bi) - { - keep_p = false; - /* Keep optional reloads from previous subpasses. */ - if (lra_reg_info[regno].restore_rtx == NULL_RTX - /* If the original pseudo changed its allocation, just - removing the optional pseudo is dangerous as the original - pseudo will have longer live range. */ - || reg_renumber[REGNO (lra_reg_info[regno].restore_rtx)] >= 0) - keep_p = true; - else if (reg_renumber[regno] >= 0) - EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi2) - { - insn = lra_insn_recog_data[uid]->insn; - if ((set = single_set (insn)) == NULL_RTX) - continue; - src = SET_SRC (set); - dest = SET_DEST (set); - if (! REG_P (src) || ! REG_P (dest)) - continue; - if (REGNO (dest) == regno - /* Ignore insn for optional reloads itself. */ - && REGNO (lra_reg_info[regno].restore_rtx) != REGNO (src) - /* Check only inheritance on last inheritance pass. */ - && (int) REGNO (src) >= new_regno_start - /* Check that the optional reload was inherited. */ - && bitmap_bit_p (&lra_inheritance_pseudos, REGNO (src))) - { - keep_p = true; - break; - } - } - if (keep_p) - { - bitmap_clear_bit (removed_optional_reload_pseudos, regno); - if (lra_dump_file != NULL) - fprintf (lra_dump_file, "Keep optional reload reg %d\n", regno); - } - } - change_p = ! bitmap_empty_p (removed_optional_reload_pseudos); - auto_bitmap insn_bitmap (®_obstack); - EXECUTE_IF_SET_IN_BITMAP (removed_optional_reload_pseudos, 0, regno, bi) - { - if (lra_dump_file != NULL) - fprintf (lra_dump_file, "Remove optional reload reg %d\n", regno); - bitmap_copy (insn_bitmap, &lra_reg_info[regno].insn_bitmap); - EXECUTE_IF_SET_IN_BITMAP (insn_bitmap, 0, uid, bi2) - { - insn = lra_insn_recog_data[uid]->insn; - if ((set = single_set (insn)) != NULL_RTX) - { - src = SET_SRC (set); - dest = SET_DEST (set); - if (REG_P (src) && REG_P (dest) - && ((REGNO (src) == regno - && (REGNO (lra_reg_info[regno].restore_rtx) - == REGNO (dest))) - || (REGNO (dest) == regno - && (REGNO (lra_reg_info[regno].restore_rtx) - == REGNO (src))))) - { - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, " Deleting move %u\n", - INSN_UID (insn)); - dump_insn_slim (lra_dump_file, insn); - } - delete_move_and_clobber (insn, REGNO (dest)); - continue; - } - /* We should not worry about generation memory-memory - moves here as if the corresponding inheritance did - not work (inheritance pseudo did not get a hard reg), - we remove the inheritance pseudo and the optional - reload. */ - } - lra_substitute_pseudo_within_insn - (insn, regno, lra_reg_info[regno].restore_rtx, false); - lra_update_insn_regno_info (insn); - if (lra_dump_file != NULL) - { - fprintf (lra_dump_file, - " Restoring original insn:\n"); - dump_insn_slim (lra_dump_file, insn); - } - } - } - /* Clear restore_regnos. */ - EXECUTE_IF_SET_IN_BITMAP (&lra_optional_reload_pseudos, 0, regno, bi) - lra_reg_info[regno].restore_rtx = NULL_RTX; - return change_p; -} - -/* Entry function for undoing inheritance/split transformation. Return true - if we did any RTL change in this pass. */ -bool -lra_undo_inheritance (void) -{ - unsigned int regno; - int hard_regno; - int n_all_inherit, n_inherit, n_all_split, n_split; - rtx restore_rtx; - bitmap_iterator bi; - bool change_p; - - lra_undo_inheritance_iter++; - if (lra_undo_inheritance_iter > LRA_MAX_INHERITANCE_PASSES) - return false; - if (lra_dump_file != NULL) - fprintf (lra_dump_file, - "\n********** Undoing inheritance #%d: **********\n\n", - lra_undo_inheritance_iter); - auto_bitmap remove_pseudos (®_obstack); - n_inherit = n_all_inherit = 0; - EXECUTE_IF_SET_IN_BITMAP (&lra_inheritance_pseudos, 0, regno, bi) - if (lra_reg_info[regno].restore_rtx != NULL_RTX) - { - n_all_inherit++; - if (reg_renumber[regno] < 0 - /* If the original pseudo changed its allocation, just - removing inheritance is dangerous as for changing - allocation we used shorter live-ranges. */ - && (! REG_P (lra_reg_info[regno].restore_rtx) - || reg_renumber[REGNO (lra_reg_info[regno].restore_rtx)] < 0)) - bitmap_set_bit (remove_pseudos, regno); - else - n_inherit++; - } - if (lra_dump_file != NULL && n_all_inherit != 0) - fprintf (lra_dump_file, "Inherit %d out of %d (%.2f%%)\n", - n_inherit, n_all_inherit, - (double) n_inherit / n_all_inherit * 100); - n_split = n_all_split = 0; - EXECUTE_IF_SET_IN_BITMAP (&lra_split_regs, 0, regno, bi) - if ((restore_rtx = lra_reg_info[regno].restore_rtx) != NULL_RTX) - { - int restore_regno = REGNO (restore_rtx); - - n_all_split++; - hard_regno = (restore_regno >= FIRST_PSEUDO_REGISTER - ? reg_renumber[restore_regno] : restore_regno); - if (hard_regno < 0 || reg_renumber[regno] == hard_regno) - bitmap_set_bit (remove_pseudos, regno); - else - { - n_split++; - if (lra_dump_file != NULL) - fprintf (lra_dump_file, " Keep split r%d (orig=r%d)\n", - regno, restore_regno); - } - } - if (lra_dump_file != NULL && n_all_split != 0) - fprintf (lra_dump_file, "Split %d out of %d (%.2f%%)\n", - n_split, n_all_split, - (double) n_split / n_all_split * 100); - change_p = remove_inheritance_pseudos (remove_pseudos); - /* Clear restore_regnos. */ - EXECUTE_IF_SET_IN_BITMAP (&lra_inheritance_pseudos, 0, regno, bi) - lra_reg_info[regno].restore_rtx = NULL_RTX; - EXECUTE_IF_SET_IN_BITMAP (&lra_split_regs, 0, regno, bi) - lra_reg_info[regno].restore_rtx = NULL_RTX; - change_p = undo_optional_reloads () || change_p; - return change_p; -} |