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/fortran/frontend-passes.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/fortran/frontend-passes.c')
-rw-r--r-- | gcc/fortran/frontend-passes.c | 5951 |
1 files changed, 0 insertions, 5951 deletions
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c deleted file mode 100644 index 22f1bb5..0000000 --- a/gcc/fortran/frontend-passes.c +++ /dev/null @@ -1,5951 +0,0 @@ -/* Pass manager for Fortran front end. - Copyright (C) 2010-2022 Free Software Foundation, Inc. - Contributed by Thomas König. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "options.h" -#include "gfortran.h" -#include "dependency.h" -#include "constructor.h" -#include "intrinsic.h" - -/* Forward declarations. */ - -static void strip_function_call (gfc_expr *); -static void optimize_namespace (gfc_namespace *); -static void optimize_assignment (gfc_code *); -static bool optimize_op (gfc_expr *); -static bool optimize_comparison (gfc_expr *, gfc_intrinsic_op); -static bool optimize_trim (gfc_expr *); -static bool optimize_lexical_comparison (gfc_expr *); -static void optimize_minmaxloc (gfc_expr **); -static bool is_empty_string (gfc_expr *e); -static void doloop_warn (gfc_namespace *); -static int do_intent (gfc_expr **); -static int do_subscript (gfc_expr **); -static void optimize_reduction (gfc_namespace *); -static int callback_reduction (gfc_expr **, int *, void *); -static void realloc_strings (gfc_namespace *); -static gfc_expr *create_var (gfc_expr *, const char *vname=NULL); -static int matmul_to_var_expr (gfc_expr **, int *, void *); -static int matmul_to_var_code (gfc_code **, int *, void *); -static int inline_matmul_assign (gfc_code **, int *, void *); -static gfc_code * create_do_loop (gfc_expr *, gfc_expr *, gfc_expr *, - locus *, gfc_namespace *, - char *vname=NULL); -static gfc_expr* check_conjg_transpose_variable (gfc_expr *, bool *, - bool *); -static int call_external_blas (gfc_code **, int *, void *); -static int matmul_temp_args (gfc_code **, int *,void *data); -static int index_interchange (gfc_code **, int*, void *); -static bool is_fe_temp (gfc_expr *e); - -#ifdef CHECKING_P -static void check_locus (gfc_namespace *); -#endif - -/* How deep we are inside an argument list. */ - -static int count_arglist; - -/* Vector of gfc_expr ** we operate on. */ - -static vec<gfc_expr **> expr_array; - -/* Pointer to the gfc_code we currently work on - to be able to insert - a block before the statement. */ - -static gfc_code **current_code; - -/* Pointer to the block to be inserted, and the statement we are - changing within the block. */ - -static gfc_code *inserted_block, **changed_statement; - -/* The namespace we are currently dealing with. */ - -static gfc_namespace *current_ns; - -/* If we are within any forall loop. */ - -static int forall_level; - -/* Keep track of whether we are within an OMP workshare. */ - -static bool in_omp_workshare; - -/* Keep track of whether we are within an OMP atomic. */ - -static bool in_omp_atomic; - -/* Keep track of whether we are within a WHERE statement. */ - -static bool in_where; - -/* Keep track of iterators for array constructors. */ - -static int iterator_level; - -/* Keep track of DO loop levels. */ - -typedef struct { - gfc_code *c; - int branch_level; - bool seen_goto; -} do_t; - -static vec<do_t> doloop_list; -static int doloop_level; - -/* Keep track of if and select case levels. */ - -static int if_level; -static int select_level; - -/* Vector of gfc_expr * to keep track of DO loops. */ - -struct my_struct *evec; - -/* Keep track of association lists. */ - -static bool in_assoc_list; - -/* Counter for temporary variables. */ - -static int var_num = 1; - -/* What sort of matrix we are dealing with when inlining MATMUL. */ - -enum matrix_case { none=0, A2B2, A2B1, A1B2, A2B2T, A2TB2, A2TB2T }; - -/* Keep track of the number of expressions we have inserted so far - using create_var. */ - -int n_vars; - -/* Entry point - run all passes for a namespace. */ - -void -gfc_run_passes (gfc_namespace *ns) -{ - - /* Warn about dubious DO loops where the index might - change. */ - - doloop_level = 0; - if_level = 0; - select_level = 0; - doloop_warn (ns); - doloop_list.release (); - int w, e; - -#ifdef CHECKING_P - check_locus (ns); -#endif - - gfc_get_errors (&w, &e); - if (e > 0) - return; - - if (flag_frontend_optimize || flag_frontend_loop_interchange) - optimize_namespace (ns); - - if (flag_frontend_optimize) - { - optimize_reduction (ns); - if (flag_dump_fortran_optimized) - gfc_dump_parse_tree (ns, stdout); - - expr_array.release (); - } - - if (flag_realloc_lhs) - realloc_strings (ns); -} - -#ifdef CHECKING_P - -/* Callback function: Warn if there is no location information in a - statement. */ - -static int -check_locus_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - current_code = c; - if (c && *c && (((*c)->loc.nextc == NULL) || ((*c)->loc.lb == NULL))) - gfc_warning_internal (0, "Inconsistent internal state: " - "No location in statement"); - - return 0; -} - - -/* Callback function: Warn if there is no location information in an - expression. */ - -static int -check_locus_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - - if (e && *e && (((*e)->where.nextc == NULL || (*e)->where.lb == NULL))) - gfc_warning_internal (0, "Inconsistent internal state: " - "No location in expression near %L", - &((*current_code)->loc)); - return 0; -} - -/* Run check for missing location information. */ - -static void -check_locus (gfc_namespace *ns) -{ - gfc_code_walker (&ns->code, check_locus_code, check_locus_expr, NULL); - - for (ns = ns->contained; ns; ns = ns->sibling) - { - if (ns->code == NULL || ns->code->op != EXEC_BLOCK) - check_locus (ns); - } -} - -#endif - -/* Callback for each gfc_code node invoked from check_realloc_strings. - For an allocatable LHS string which also appears as a variable on - the RHS, replace - - a = a(x:y) - - with - - tmp = a(x:y) - a = tmp - */ - -static int -realloc_string_callback (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - gfc_expr *expr1, *expr2; - gfc_code *co = *c; - gfc_expr *n; - gfc_ref *ref; - bool found_substr; - - if (co->op != EXEC_ASSIGN) - return 0; - - expr1 = co->expr1; - if (expr1->ts.type != BT_CHARACTER - || !gfc_expr_attr(expr1).allocatable - || !expr1->ts.deferred) - return 0; - - if (is_fe_temp (expr1)) - return 0; - - expr2 = gfc_discard_nops (co->expr2); - - if (expr2->expr_type == EXPR_VARIABLE) - { - found_substr = false; - for (ref = expr2->ref; ref; ref = ref->next) - { - if (ref->type == REF_SUBSTRING) - { - found_substr = true; - break; - } - } - if (!found_substr) - return 0; - } - else if (expr2->expr_type != EXPR_ARRAY - && (expr2->expr_type != EXPR_OP - || expr2->value.op.op != INTRINSIC_CONCAT)) - return 0; - - if (!gfc_check_dependency (expr1, expr2, true)) - return 0; - - /* gfc_check_dependency doesn't always pick up identical expressions. - However, eliminating the above sends the compiler into an infinite - loop on valid expressions. Without this check, the gimplifier emits - an ICE for a = a, where a is deferred character length. */ - if (!gfc_dep_compare_expr (expr1, expr2)) - return 0; - - current_code = c; - inserted_block = NULL; - changed_statement = NULL; - n = create_var (expr2, "realloc_string"); - co->expr2 = n; - return 0; -} - -/* Callback for each gfc_code node invoked through gfc_code_walker - from optimize_namespace. */ - -static int -optimize_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - - gfc_exec_op op; - - op = (*c)->op; - - if (op == EXEC_CALL || op == EXEC_COMPCALL || op == EXEC_ASSIGN_CALL - || op == EXEC_CALL_PPC) - count_arglist = 1; - else - count_arglist = 0; - - current_code = c; - inserted_block = NULL; - changed_statement = NULL; - - if (op == EXEC_ASSIGN) - optimize_assignment (*c); - return 0; -} - -/* Callback for each gfc_expr node invoked through gfc_code_walker - from optimize_namespace. */ - -static int -optimize_expr (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - bool function_expr; - - if ((*e)->expr_type == EXPR_FUNCTION) - { - count_arglist ++; - function_expr = true; - } - else - function_expr = false; - - if (optimize_trim (*e)) - gfc_simplify_expr (*e, 0); - - if (optimize_lexical_comparison (*e)) - gfc_simplify_expr (*e, 0); - - if ((*e)->expr_type == EXPR_OP && optimize_op (*e)) - gfc_simplify_expr (*e, 0); - - if ((*e)->expr_type == EXPR_FUNCTION && (*e)->value.function.isym) - switch ((*e)->value.function.isym->id) - { - case GFC_ISYM_MINLOC: - case GFC_ISYM_MAXLOC: - optimize_minmaxloc (e); - break; - default: - break; - } - - if (function_expr) - count_arglist --; - - return 0; -} - -/* Auxiliary function to handle the arguments to reduction intrinsics. If the - function is a scalar, just copy it; otherwise returns the new element, the - old one can be freed. */ - -static gfc_expr * -copy_walk_reduction_arg (gfc_constructor *c, gfc_expr *fn) -{ - gfc_expr *fcn, *e = c->expr; - - fcn = gfc_copy_expr (e); - if (c->iterator) - { - gfc_constructor_base newbase; - gfc_expr *new_expr; - gfc_constructor *new_c; - - newbase = NULL; - new_expr = gfc_get_expr (); - new_expr->expr_type = EXPR_ARRAY; - new_expr->ts = e->ts; - new_expr->where = e->where; - new_expr->rank = 1; - new_c = gfc_constructor_append_expr (&newbase, fcn, &(e->where)); - new_c->iterator = c->iterator; - new_expr->value.constructor = newbase; - c->iterator = NULL; - - fcn = new_expr; - } - - if (fcn->rank != 0) - { - gfc_isym_id id = fn->value.function.isym->id; - - if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT) - fcn = gfc_build_intrinsic_call (current_ns, id, - fn->value.function.isym->name, - fn->where, 3, fcn, NULL, NULL); - else if (id == GFC_ISYM_ANY || id == GFC_ISYM_ALL) - fcn = gfc_build_intrinsic_call (current_ns, id, - fn->value.function.isym->name, - fn->where, 2, fcn, NULL); - else - gfc_internal_error ("Illegal id in copy_walk_reduction_arg"); - - fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE; - } - - return fcn; -} - -/* Callback function for optimzation of reductions to scalars. Transform ANY - ([f1,f2,f3, ...]) to f1 .or. f2 .or. f3 .or. ..., with ANY, SUM and PRODUCT - correspondingly. Handly only the simple cases without MASK and DIM. */ - -static int -callback_reduction (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - gfc_expr *fn, *arg; - gfc_intrinsic_op op; - gfc_isym_id id; - gfc_actual_arglist *a; - gfc_actual_arglist *dim; - gfc_constructor *c; - gfc_expr *res, *new_expr; - gfc_actual_arglist *mask; - - fn = *e; - - if (fn->rank != 0 || fn->expr_type != EXPR_FUNCTION - || fn->value.function.isym == NULL) - return 0; - - id = fn->value.function.isym->id; - - if (id != GFC_ISYM_SUM && id != GFC_ISYM_PRODUCT - && id != GFC_ISYM_ANY && id != GFC_ISYM_ALL) - return 0; - - a = fn->value.function.actual; - - /* Don't handle MASK or DIM. */ - - dim = a->next; - - if (dim->expr != NULL) - return 0; - - if (id == GFC_ISYM_SUM || id == GFC_ISYM_PRODUCT) - { - mask = dim->next; - if ( mask->expr != NULL) - return 0; - } - - arg = a->expr; - - if (arg->expr_type != EXPR_ARRAY) - return 0; - - switch (id) - { - case GFC_ISYM_SUM: - op = INTRINSIC_PLUS; - break; - - case GFC_ISYM_PRODUCT: - op = INTRINSIC_TIMES; - break; - - case GFC_ISYM_ANY: - op = INTRINSIC_OR; - break; - - case GFC_ISYM_ALL: - op = INTRINSIC_AND; - break; - - default: - return 0; - } - - c = gfc_constructor_first (arg->value.constructor); - - /* Don't do any simplififcation if we have - - no element in the constructor or - - only have a single element in the array which contains an - iterator. */ - - if (c == NULL) - return 0; - - res = copy_walk_reduction_arg (c, fn); - - c = gfc_constructor_next (c); - while (c) - { - new_expr = gfc_get_expr (); - new_expr->ts = fn->ts; - new_expr->expr_type = EXPR_OP; - new_expr->rank = fn->rank; - new_expr->where = fn->where; - new_expr->value.op.op = op; - new_expr->value.op.op1 = res; - new_expr->value.op.op2 = copy_walk_reduction_arg (c, fn); - res = new_expr; - c = gfc_constructor_next (c); - } - - gfc_simplify_expr (res, 0); - *e = res; - gfc_free_expr (fn); - - return 0; -} - -/* Callback function for common function elimination, called from cfe_expr_0. - Put all eligible function expressions into expr_array. */ - -static int -cfe_register_funcs (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - - if ((*e)->expr_type != EXPR_FUNCTION) - return 0; - - /* We don't do character functions with unknown charlens. */ - if ((*e)->ts.type == BT_CHARACTER - && ((*e)->ts.u.cl == NULL || (*e)->ts.u.cl->length == NULL - || (*e)->ts.u.cl->length->expr_type != EXPR_CONSTANT)) - return 0; - - /* We don't do function elimination within FORALL statements, it can - lead to wrong-code in certain circumstances. */ - - if (forall_level > 0) - return 0; - - /* Function elimination inside an iterator could lead to functions which - depend on iterator variables being moved outside. FIXME: We should check - if the functions do indeed depend on the iterator variable. */ - - if (iterator_level > 0) - return 0; - - /* If we don't know the shape at compile time, we create an allocatable - temporary variable to hold the intermediate result, but only if - allocation on assignment is active. */ - - if ((*e)->rank > 0 && (*e)->shape == NULL && !flag_realloc_lhs) - return 0; - - /* Skip the test for pure functions if -faggressive-function-elimination - is specified. */ - if ((*e)->value.function.esym) - { - /* Don't create an array temporary for elemental functions. */ - if ((*e)->value.function.esym->attr.elemental && (*e)->rank > 0) - return 0; - - /* Only eliminate potentially impure functions if the - user specifically requested it. */ - if (!flag_aggressive_function_elimination - && !(*e)->value.function.esym->attr.pure - && !(*e)->value.function.esym->attr.implicit_pure) - return 0; - } - - if ((*e)->value.function.isym) - { - /* Conversions are handled on the fly by the middle end, - transpose during trans-* stages and TRANSFER by the middle end. */ - if ((*e)->value.function.isym->id == GFC_ISYM_CONVERSION - || (*e)->value.function.isym->id == GFC_ISYM_TRANSFER - || gfc_inline_intrinsic_function_p (*e)) - return 0; - - /* Don't create an array temporary for elemental functions, - as this would be wasteful of memory. - FIXME: Create a scalar temporary during scalarization. */ - if ((*e)->value.function.isym->elemental && (*e)->rank > 0) - return 0; - - if (!(*e)->value.function.isym->pure) - return 0; - } - - expr_array.safe_push (e); - return 0; -} - -/* Auxiliary function to check if an expression is a temporary created by - create var. */ - -static bool -is_fe_temp (gfc_expr *e) -{ - if (e->expr_type != EXPR_VARIABLE) - return false; - - return e->symtree->n.sym->attr.fe_temp; -} - -/* Determine the length of a string, if it can be evaluated as a constant - expression. Return a newly allocated gfc_expr or NULL on failure. - If the user specified a substring which is potentially longer than - the string itself, the string will be padded with spaces, which - is harmless. */ - -static gfc_expr * -constant_string_length (gfc_expr *e) -{ - - gfc_expr *length; - gfc_ref *ref; - gfc_expr *res; - mpz_t value; - - if (e->ts.u.cl) - { - length = e->ts.u.cl->length; - if (length && length->expr_type == EXPR_CONSTANT) - return gfc_copy_expr(length); - } - - /* See if there is a substring. If it has a constant length, return - that and NULL otherwise. */ - for (ref = e->ref; ref; ref = ref->next) - { - if (ref->type == REF_SUBSTRING) - { - if (gfc_dep_difference (ref->u.ss.end, ref->u.ss.start, &value)) - { - res = gfc_get_constant_expr (BT_INTEGER, gfc_charlen_int_kind, - &e->where); - - mpz_add_ui (res->value.integer, value, 1); - mpz_clear (value); - return res; - } - else - return NULL; - } - } - - /* Return length of char symbol, if constant. */ - if (e->symtree && e->symtree->n.sym->ts.u.cl - && e->symtree->n.sym->ts.u.cl->length - && e->symtree->n.sym->ts.u.cl->length->expr_type == EXPR_CONSTANT) - return gfc_copy_expr (e->symtree->n.sym->ts.u.cl->length); - - return NULL; - -} - -/* Insert a block at the current position unless it has already - been inserted; in this case use the one already there. */ - -static gfc_namespace* -insert_block () -{ - gfc_namespace *ns; - - /* If the block hasn't already been created, do so. */ - if (inserted_block == NULL) - { - inserted_block = XCNEW (gfc_code); - inserted_block->op = EXEC_BLOCK; - inserted_block->loc = (*current_code)->loc; - ns = gfc_build_block_ns (current_ns); - inserted_block->ext.block.ns = ns; - inserted_block->ext.block.assoc = NULL; - - ns->code = *current_code; - - /* If the statement has a label, make sure it is transferred to - the newly created block. */ - - if ((*current_code)->here) - { - inserted_block->here = (*current_code)->here; - (*current_code)->here = NULL; - } - - inserted_block->next = (*current_code)->next; - changed_statement = &(inserted_block->ext.block.ns->code); - (*current_code)->next = NULL; - /* Insert the BLOCK at the right position. */ - *current_code = inserted_block; - ns->parent = current_ns; - } - else - ns = inserted_block->ext.block.ns; - - return ns; -} - - -/* Insert a call to the intrinsic len. Use a different name for - the symbol tree so we don't run into trouble when the user has - renamed len for some reason. */ - -static gfc_expr* -get_len_call (gfc_expr *str) -{ - gfc_expr *fcn; - gfc_actual_arglist *actual_arglist; - - fcn = gfc_get_expr (); - fcn->expr_type = EXPR_FUNCTION; - fcn->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LEN); - actual_arglist = gfc_get_actual_arglist (); - actual_arglist->expr = str; - - fcn->value.function.actual = actual_arglist; - fcn->where = str->where; - fcn->ts.type = BT_INTEGER; - fcn->ts.kind = gfc_charlen_int_kind; - - gfc_get_sym_tree ("__internal_len", current_ns, &fcn->symtree, false); - fcn->symtree->n.sym->ts = fcn->ts; - fcn->symtree->n.sym->attr.flavor = FL_PROCEDURE; - fcn->symtree->n.sym->attr.function = 1; - fcn->symtree->n.sym->attr.elemental = 1; - fcn->symtree->n.sym->attr.referenced = 1; - fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE; - gfc_commit_symbol (fcn->symtree->n.sym); - - return fcn; -} - - -/* Returns a new expression (a variable) to be used in place of the old one, - with an optional assignment statement before the current statement to set - the value of the variable. Creates a new BLOCK for the statement if that - hasn't already been done and puts the statement, plus the newly created - variables, in that block. Special cases: If the expression is constant or - a temporary which has already been created, just copy it. */ - -static gfc_expr* -create_var (gfc_expr * e, const char *vname) -{ - char name[GFC_MAX_SYMBOL_LEN +1]; - gfc_symtree *symtree; - gfc_symbol *symbol; - gfc_expr *result; - gfc_code *n; - gfc_namespace *ns; - int i; - bool deferred; - - if (e->expr_type == EXPR_CONSTANT || is_fe_temp (e)) - return gfc_copy_expr (e); - - /* Creation of an array of unknown size requires realloc on assignment. - If that is not possible, just return NULL. */ - if (flag_realloc_lhs == 0 && e->rank > 0 && e->shape == NULL) - return NULL; - - ns = insert_block (); - - if (vname) - snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d_%s", var_num++, vname); - else - snprintf (name, GFC_MAX_SYMBOL_LEN, "__var_%d", var_num++); - - if (gfc_get_sym_tree (name, ns, &symtree, false) != 0) - gcc_unreachable (); - - symbol = symtree->n.sym; - symbol->ts = e->ts; - - if (e->rank > 0) - { - symbol->as = gfc_get_array_spec (); - symbol->as->rank = e->rank; - - if (e->shape == NULL) - { - /* We don't know the shape at compile time, so we use an - allocatable. */ - symbol->as->type = AS_DEFERRED; - symbol->attr.allocatable = 1; - } - else - { - symbol->as->type = AS_EXPLICIT; - /* Copy the shape. */ - for (i=0; i<e->rank; i++) - { - gfc_expr *p, *q; - - p = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind, - &(e->where)); - mpz_set_si (p->value.integer, 1); - symbol->as->lower[i] = p; - - q = gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind, - &(e->where)); - mpz_set (q->value.integer, e->shape[i]); - symbol->as->upper[i] = q; - } - } - } - - deferred = 0; - if (e->ts.type == BT_CHARACTER) - { - gfc_expr *length; - - symbol->ts.u.cl = gfc_new_charlen (ns, NULL); - length = constant_string_length (e); - if (length) - symbol->ts.u.cl->length = length; - else if (e->expr_type == EXPR_VARIABLE - && e->symtree->n.sym->ts.type == BT_CHARACTER - && e->ts.u.cl->length) - symbol->ts.u.cl->length = get_len_call (gfc_copy_expr (e)); - else - { - symbol->attr.allocatable = 1; - symbol->ts.u.cl->length = NULL; - symbol->ts.deferred = 1; - deferred = 1; - } - } - - symbol->attr.flavor = FL_VARIABLE; - symbol->attr.referenced = 1; - symbol->attr.dimension = e->rank > 0; - symbol->attr.fe_temp = 1; - gfc_commit_symbol (symbol); - - result = gfc_get_expr (); - result->expr_type = EXPR_VARIABLE; - result->ts = symbol->ts; - result->ts.deferred = deferred; - result->rank = e->rank; - result->shape = gfc_copy_shape (e->shape, e->rank); - result->symtree = symtree; - result->where = e->where; - if (e->rank > 0) - { - result->ref = gfc_get_ref (); - result->ref->type = REF_ARRAY; - result->ref->u.ar.type = AR_FULL; - result->ref->u.ar.where = e->where; - result->ref->u.ar.dimen = e->rank; - result->ref->u.ar.as = symbol->ts.type == BT_CLASS - ? CLASS_DATA (symbol)->as : symbol->as; - if (warn_array_temporaries) - gfc_warning (OPT_Warray_temporaries, - "Creating array temporary at %L", &(e->where)); - } - - /* Generate the new assignment. */ - n = XCNEW (gfc_code); - n->op = EXEC_ASSIGN; - n->loc = (*current_code)->loc; - n->next = *changed_statement; - n->expr1 = gfc_copy_expr (result); - n->expr2 = e; - *changed_statement = n; - n_vars ++; - - return result; -} - -/* Warn about function elimination. */ - -static void -do_warn_function_elimination (gfc_expr *e) -{ - const char *name; - if (e->expr_type == EXPR_FUNCTION - && !gfc_pure_function (e, &name) && !gfc_implicit_pure_function (e)) - { - if (name) - gfc_warning (OPT_Wfunction_elimination, - "Removing call to impure function %qs at %L", name, - &(e->where)); - else - gfc_warning (OPT_Wfunction_elimination, - "Removing call to impure function at %L", - &(e->where)); - } -} - - -/* Callback function for the code walker for doing common function - elimination. This builds up the list of functions in the expression - and goes through them to detect duplicates, which it then replaces - by variables. */ - -static int -cfe_expr_0 (gfc_expr **e, int *walk_subtrees, - void *data ATTRIBUTE_UNUSED) -{ - int i,j; - gfc_expr *newvar; - gfc_expr **ei, **ej; - - /* Don't do this optimization within OMP workshare/atomic or ASSOC lists. */ - - if (in_omp_workshare || in_omp_atomic || in_assoc_list) - { - *walk_subtrees = 0; - return 0; - } - - expr_array.release (); - - gfc_expr_walker (e, cfe_register_funcs, NULL); - - /* Walk through all the functions. */ - - FOR_EACH_VEC_ELT_FROM (expr_array, i, ei, 1) - { - /* Skip if the function has been replaced by a variable already. */ - if ((*ei)->expr_type == EXPR_VARIABLE) - continue; - - newvar = NULL; - for (j=0; j<i; j++) - { - ej = expr_array[j]; - if (gfc_dep_compare_functions (*ei, *ej, true) == 0) - { - if (newvar == NULL) - newvar = create_var (*ei, "fcn"); - - if (warn_function_elimination) - do_warn_function_elimination (*ej); - - free (*ej); - *ej = gfc_copy_expr (newvar); - } - } - if (newvar) - *ei = newvar; - } - - /* We did all the necessary walking in this function. */ - *walk_subtrees = 0; - return 0; -} - -/* Callback function for common function elimination, called from - gfc_code_walker. This keeps track of the current code, in order - to insert statements as needed. */ - -static int -cfe_code (gfc_code **c, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) -{ - current_code = c; - inserted_block = NULL; - changed_statement = NULL; - - /* Do not do anything inside a WHERE statement; scalar assignments, BLOCKs - and allocation on assigment are prohibited inside WHERE, and finally - masking an expression would lead to wrong-code when replacing - - WHERE (a>0) - b = sum(foo(a) + foo(a)) - END WHERE - - with - - WHERE (a > 0) - tmp = foo(a) - b = sum(tmp + tmp) - END WHERE -*/ - - if ((*c)->op == EXEC_WHERE) - { - *walk_subtrees = 0; - return 0; - } - - - return 0; -} - -/* Dummy function for expression call back, for use when we - really don't want to do any walking. */ - -static int -dummy_expr_callback (gfc_expr **e ATTRIBUTE_UNUSED, int *walk_subtrees, - void *data ATTRIBUTE_UNUSED) -{ - *walk_subtrees = 0; - return 0; -} - -/* Dummy function for code callback, for use when we really - don't want to do anything. */ -int -gfc_dummy_code_callback (gfc_code **e ATTRIBUTE_UNUSED, - int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - return 0; -} - -/* Code callback function for converting - do while(a) - end do - into the equivalent - do - if (.not. a) exit - end do - This is because common function elimination would otherwise place the - temporary variables outside the loop. */ - -static int -convert_do_while (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - gfc_code *co = *c; - gfc_code *c_if1, *c_if2, *c_exit; - gfc_code *loopblock; - gfc_expr *e_not, *e_cond; - - if (co->op != EXEC_DO_WHILE) - return 0; - - if (co->expr1 == NULL || co->expr1->expr_type == EXPR_CONSTANT) - return 0; - - e_cond = co->expr1; - - /* Generate the condition of the if statement, which is .not. the original - statement. */ - e_not = gfc_get_expr (); - e_not->ts = e_cond->ts; - e_not->where = e_cond->where; - e_not->expr_type = EXPR_OP; - e_not->value.op.op = INTRINSIC_NOT; - e_not->value.op.op1 = e_cond; - - /* Generate the EXIT statement. */ - c_exit = XCNEW (gfc_code); - c_exit->op = EXEC_EXIT; - c_exit->ext.which_construct = co; - c_exit->loc = co->loc; - - /* Generate the IF statement. */ - c_if2 = XCNEW (gfc_code); - c_if2->op = EXEC_IF; - c_if2->expr1 = e_not; - c_if2->next = c_exit; - c_if2->loc = co->loc; - - /* ... plus the one to chain it to. */ - c_if1 = XCNEW (gfc_code); - c_if1->op = EXEC_IF; - c_if1->block = c_if2; - c_if1->loc = co->loc; - - /* Make the DO WHILE loop into a DO block by replacing the condition - with a true constant. */ - co->expr1 = gfc_get_logical_expr (gfc_default_integer_kind, &co->loc, true); - - /* Hang the generated if statement into the loop body. */ - - loopblock = co->block->next; - co->block->next = c_if1; - c_if1->next = loopblock; - - return 0; -} - -/* Code callback function for converting - if (a) then - ... - else if (b) then - end if - - into - if (a) then - else - if (b) then - end if - end if - - because otherwise common function elimination would place the BLOCKs - into the wrong place. */ - -static int -convert_elseif (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - gfc_code *co = *c; - gfc_code *c_if1, *c_if2, *else_stmt; - - if (co->op != EXEC_IF) - return 0; - - /* This loop starts out with the first ELSE statement. */ - else_stmt = co->block->block; - - while (else_stmt != NULL) - { - gfc_code *next_else; - - /* If there is no condition, we're done. */ - if (else_stmt->expr1 == NULL) - break; - - next_else = else_stmt->block; - - /* Generate the new IF statement. */ - c_if2 = XCNEW (gfc_code); - c_if2->op = EXEC_IF; - c_if2->expr1 = else_stmt->expr1; - c_if2->next = else_stmt->next; - c_if2->loc = else_stmt->loc; - c_if2->block = next_else; - - /* ... plus the one to chain it to. */ - c_if1 = XCNEW (gfc_code); - c_if1->op = EXEC_IF; - c_if1->block = c_if2; - c_if1->loc = else_stmt->loc; - - /* Insert the new IF after the ELSE. */ - else_stmt->expr1 = NULL; - else_stmt->next = c_if1; - else_stmt->block = NULL; - - else_stmt = next_else; - } - /* Don't walk subtrees. */ - return 0; -} - -/* Callback function to var_in_expr - return true if expr1 and - expr2 are identical variables. */ -static int -var_in_expr_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data) -{ - gfc_expr *expr1 = (gfc_expr *) data; - gfc_expr *expr2 = *e; - - if (expr2->expr_type != EXPR_VARIABLE) - return 0; - - return expr1->symtree->n.sym == expr2->symtree->n.sym; -} - -/* Return true if expr1 is found in expr2. */ - -static bool -var_in_expr (gfc_expr *expr1, gfc_expr *expr2) -{ - gcc_assert (expr1->expr_type == EXPR_VARIABLE); - - return gfc_expr_walker (&expr2, var_in_expr_callback, (void *) expr1); -} - -struct do_stack -{ - struct do_stack *prev; - gfc_iterator *iter; - gfc_code *code; -} *stack_top; - -/* Recursively traverse the block of a WRITE or READ statement, and maybe - optimize by replacing do loops with their analog array slices. For - example: - - write (*,*) (a(i), i=1,4) - - is replaced with - - write (*,*) a(1:4:1) . */ - -static bool -traverse_io_block (gfc_code *code, bool *has_reached, gfc_code *prev) -{ - gfc_code *curr; - gfc_expr *new_e, *expr, *start; - gfc_ref *ref; - struct do_stack ds_push; - int i, future_rank = 0; - gfc_iterator *iters[GFC_MAX_DIMENSIONS]; - gfc_expr *e; - - /* Find the first transfer/do statement. */ - for (curr = code; curr; curr = curr->next) - { - if (curr->op == EXEC_DO || curr->op == EXEC_TRANSFER) - break; - } - - /* Ensure it is the only transfer/do statement because cases like - - write (*,*) (a(i), b(i), i=1,4) - - cannot be optimized. */ - - if (!curr || curr->next) - return false; - - if (curr->op == EXEC_DO) - { - if (curr->ext.iterator->var->ref) - return false; - ds_push.prev = stack_top; - ds_push.iter = curr->ext.iterator; - ds_push.code = curr; - stack_top = &ds_push; - if (traverse_io_block (curr->block->next, has_reached, prev)) - { - if (curr != stack_top->code && !*has_reached) - { - curr->block->next = NULL; - gfc_free_statements (curr); - } - else - *has_reached = true; - return true; - } - return false; - } - - gcc_assert (curr->op == EXEC_TRANSFER); - - e = curr->expr1; - ref = e->ref; - if (!ref || ref->type != REF_ARRAY || ref->u.ar.codimen != 0 || ref->next) - return false; - - /* Find the iterators belonging to each variable and check conditions. */ - for (i = 0; i < ref->u.ar.dimen; i++) - { - if (!ref->u.ar.start[i] || ref->u.ar.start[i]->ref - || ref->u.ar.dimen_type[i] != DIMEN_ELEMENT) - return false; - - start = ref->u.ar.start[i]; - gfc_simplify_expr (start, 0); - switch (start->expr_type) - { - case EXPR_VARIABLE: - - /* write (*,*) (a(i), i=a%b,1) not handled yet. */ - if (start->ref) - return false; - - /* Check for (a(k), i=1,4) or ((a(j, i), i=1,4), j=1,4). */ - if (!stack_top || !stack_top->iter - || stack_top->iter->var->symtree != start->symtree) - { - /* Check for (a(i,i), i=1,3). */ - int j; - - for (j=0; j<i; j++) - if (iters[j] && iters[j]->var->symtree == start->symtree) - return false; - - iters[i] = NULL; - } - else - { - iters[i] = stack_top->iter; - stack_top = stack_top->prev; - future_rank++; - } - break; - case EXPR_CONSTANT: - iters[i] = NULL; - break; - case EXPR_OP: - switch (start->value.op.op) - { - case INTRINSIC_PLUS: - case INTRINSIC_TIMES: - if (start->value.op.op1->expr_type != EXPR_VARIABLE) - std::swap (start->value.op.op1, start->value.op.op2); - gcc_fallthrough (); - case INTRINSIC_MINUS: - if (start->value.op.op1->expr_type!= EXPR_VARIABLE - || start->value.op.op2->expr_type != EXPR_CONSTANT - || start->value.op.op1->ref) - return false; - if (!stack_top || !stack_top->iter - || stack_top->iter->var->symtree - != start->value.op.op1->symtree) - return false; - iters[i] = stack_top->iter; - stack_top = stack_top->prev; - break; - default: - return false; - } - future_rank++; - break; - default: - return false; - } - } - - /* Check for cases like ((a(i, j), i=1, j), j=1, 2). */ - for (int i = 1; i < ref->u.ar.dimen; i++) - { - if (iters[i]) - { - gfc_expr *var = iters[i]->var; - for (int j = i - 1; j < i; j++) - { - if (iters[j] - && (var_in_expr (var, iters[j]->start) - || var_in_expr (var, iters[j]->end) - || var_in_expr (var, iters[j]->step))) - return false; - } - } - } - - /* Create new expr. */ - new_e = gfc_copy_expr (curr->expr1); - new_e->expr_type = EXPR_VARIABLE; - new_e->rank = future_rank; - if (curr->expr1->shape) - new_e->shape = gfc_get_shape (new_e->rank); - - /* Assign new starts, ends and strides if necessary. */ - for (i = 0; i < ref->u.ar.dimen; i++) - { - if (!iters[i]) - continue; - start = ref->u.ar.start[i]; - switch (start->expr_type) - { - case EXPR_CONSTANT: - gfc_internal_error ("bad expression"); - break; - case EXPR_VARIABLE: - new_e->ref->u.ar.dimen_type[i] = DIMEN_RANGE; - new_e->ref->u.ar.type = AR_SECTION; - gfc_free_expr (new_e->ref->u.ar.start[i]); - new_e->ref->u.ar.start[i] = gfc_copy_expr (iters[i]->start); - new_e->ref->u.ar.end[i] = gfc_copy_expr (iters[i]->end); - new_e->ref->u.ar.stride[i] = gfc_copy_expr (iters[i]->step); - break; - case EXPR_OP: - new_e->ref->u.ar.dimen_type[i] = DIMEN_RANGE; - new_e->ref->u.ar.type = AR_SECTION; - gfc_free_expr (new_e->ref->u.ar.start[i]); - expr = gfc_copy_expr (start); - expr->value.op.op1 = gfc_copy_expr (iters[i]->start); - new_e->ref->u.ar.start[i] = expr; - gfc_simplify_expr (new_e->ref->u.ar.start[i], 0); - expr = gfc_copy_expr (start); - expr->value.op.op1 = gfc_copy_expr (iters[i]->end); - new_e->ref->u.ar.end[i] = expr; - gfc_simplify_expr (new_e->ref->u.ar.end[i], 0); - switch (start->value.op.op) - { - case INTRINSIC_MINUS: - case INTRINSIC_PLUS: - new_e->ref->u.ar.stride[i] = gfc_copy_expr (iters[i]->step); - break; - case INTRINSIC_TIMES: - expr = gfc_copy_expr (start); - expr->value.op.op1 = gfc_copy_expr (iters[i]->step); - new_e->ref->u.ar.stride[i] = expr; - gfc_simplify_expr (new_e->ref->u.ar.stride[i], 0); - break; - default: - gfc_internal_error ("bad op"); - } - break; - default: - gfc_internal_error ("bad expression"); - } - } - curr->expr1 = new_e; - - /* Insert modified statement. Check whether the statement needs to be - inserted at the lowest level. */ - if (!stack_top->iter) - { - if (prev) - { - curr->next = prev->next->next; - prev->next = curr; - } - else - { - curr->next = stack_top->code->block->next->next->next; - stack_top->code->block->next = curr; - } - } - else - stack_top->code->block->next = curr; - return true; -} - -/* Function for the gfc_code_walker. If code is a READ or WRITE statement, it - tries to optimize its block. */ - -static int -simplify_io_impl_do (gfc_code **code, int *walk_subtrees, - void *data ATTRIBUTE_UNUSED) -{ - gfc_code **curr, *prev = NULL; - struct do_stack write, first; - bool b = false; - *walk_subtrees = 1; - if (!(*code)->block - || ((*code)->block->op != EXEC_WRITE - && (*code)->block->op != EXEC_READ)) - return 0; - - *walk_subtrees = 0; - write.prev = NULL; - write.iter = NULL; - write.code = *code; - - for (curr = &(*code)->block; *curr; curr = &(*curr)->next) - { - if ((*curr)->op == EXEC_DO) - { - first.prev = &write; - first.iter = (*curr)->ext.iterator; - first.code = *curr; - stack_top = &first; - traverse_io_block ((*curr)->block->next, &b, prev); - stack_top = NULL; - } - prev = *curr; - } - return 0; -} - -/* Optimize a namespace, including all contained namespaces. - flag_frontend_optimize and flag_fronend_loop_interchange are - handled separately. */ - -static void -optimize_namespace (gfc_namespace *ns) -{ - gfc_namespace *saved_ns = gfc_current_ns; - current_ns = ns; - gfc_current_ns = ns; - forall_level = 0; - iterator_level = 0; - in_assoc_list = false; - in_omp_workshare = false; - in_omp_atomic = false; - - if (flag_frontend_optimize) - { - gfc_code_walker (&ns->code, simplify_io_impl_do, dummy_expr_callback, NULL); - gfc_code_walker (&ns->code, convert_do_while, dummy_expr_callback, NULL); - gfc_code_walker (&ns->code, convert_elseif, dummy_expr_callback, NULL); - gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL); - gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL); - if (flag_inline_matmul_limit != 0 || flag_external_blas) - { - bool found; - do - { - found = false; - gfc_code_walker (&ns->code, matmul_to_var_code, matmul_to_var_expr, - (void *) &found); - } - while (found); - - gfc_code_walker (&ns->code, matmul_temp_args, dummy_expr_callback, - NULL); - } - - if (flag_external_blas) - gfc_code_walker (&ns->code, call_external_blas, dummy_expr_callback, - NULL); - - if (flag_inline_matmul_limit != 0) - gfc_code_walker (&ns->code, inline_matmul_assign, dummy_expr_callback, - NULL); - } - - if (flag_frontend_loop_interchange) - gfc_code_walker (&ns->code, index_interchange, dummy_expr_callback, - NULL); - - /* BLOCKs are handled in the expression walker below. */ - for (ns = ns->contained; ns; ns = ns->sibling) - { - if (ns->code == NULL || ns->code->op != EXEC_BLOCK) - optimize_namespace (ns); - } - gfc_current_ns = saved_ns; -} - -/* Handle dependencies for allocatable strings which potentially redefine - themselves in an assignment. */ - -static void -realloc_strings (gfc_namespace *ns) -{ - current_ns = ns; - gfc_code_walker (&ns->code, realloc_string_callback, dummy_expr_callback, NULL); - - for (ns = ns->contained; ns; ns = ns->sibling) - { - if (ns->code == NULL || ns->code->op != EXEC_BLOCK) - realloc_strings (ns); - } - -} - -static void -optimize_reduction (gfc_namespace *ns) -{ - current_ns = ns; - gfc_code_walker (&ns->code, gfc_dummy_code_callback, - callback_reduction, NULL); - -/* BLOCKs are handled in the expression walker below. */ - for (ns = ns->contained; ns; ns = ns->sibling) - { - if (ns->code == NULL || ns->code->op != EXEC_BLOCK) - optimize_reduction (ns); - } -} - -/* Replace code like - a = matmul(b,c) + d - with - a = matmul(b,c) ; a = a + d - where the array function is not elemental and not allocatable - and does not depend on the left-hand side. -*/ - -static bool -optimize_binop_array_assignment (gfc_code *c, gfc_expr **rhs, bool seen_op) -{ - gfc_expr *e; - - if (!*rhs) - return false; - - e = *rhs; - if (e->expr_type == EXPR_OP) - { - switch (e->value.op.op) - { - /* Unary operators and exponentiation: Only look at a single - operand. */ - case INTRINSIC_NOT: - case INTRINSIC_UPLUS: - case INTRINSIC_UMINUS: - case INTRINSIC_PARENTHESES: - case INTRINSIC_POWER: - if (optimize_binop_array_assignment (c, &e->value.op.op1, seen_op)) - return true; - break; - - case INTRINSIC_CONCAT: - /* Do not do string concatenations. */ - break; - - default: - /* Binary operators. */ - if (optimize_binop_array_assignment (c, &e->value.op.op1, true)) - return true; - - if (optimize_binop_array_assignment (c, &e->value.op.op2, true)) - return true; - - break; - } - } - else if (seen_op && e->expr_type == EXPR_FUNCTION && e->rank > 0 - && ! (e->value.function.esym - && (e->value.function.esym->attr.elemental - || e->value.function.esym->attr.allocatable - || e->value.function.esym->ts.type != c->expr1->ts.type - || e->value.function.esym->ts.kind != c->expr1->ts.kind)) - && ! (e->value.function.isym - && (e->value.function.isym->elemental - || e->ts.type != c->expr1->ts.type - || e->ts.kind != c->expr1->ts.kind)) - && ! gfc_inline_intrinsic_function_p (e)) - { - - gfc_code *n; - gfc_expr *new_expr; - - /* Insert a new assignment statement after the current one. */ - n = XCNEW (gfc_code); - n->op = EXEC_ASSIGN; - n->loc = c->loc; - n->next = c->next; - c->next = n; - - n->expr1 = gfc_copy_expr (c->expr1); - n->expr2 = c->expr2; - new_expr = gfc_copy_expr (c->expr1); - c->expr2 = e; - *rhs = new_expr; - - return true; - - } - - /* Nothing to optimize. */ - return false; -} - -/* Remove unneeded TRIMs at the end of expressions. */ - -static bool -remove_trim (gfc_expr *rhs) -{ - bool ret; - - ret = false; - if (!rhs) - return ret; - - /* Check for a // b // trim(c). Looping is probably not - necessary because the parser usually generates - (// (// a b ) trim(c) ) , but better safe than sorry. */ - - while (rhs->expr_type == EXPR_OP - && rhs->value.op.op == INTRINSIC_CONCAT) - rhs = rhs->value.op.op2; - - while (rhs->expr_type == EXPR_FUNCTION && rhs->value.function.isym - && rhs->value.function.isym->id == GFC_ISYM_TRIM) - { - strip_function_call (rhs); - /* Recursive call to catch silly stuff like trim ( a // trim(b)). */ - remove_trim (rhs); - ret = true; - } - - return ret; -} - -/* Optimizations for an assignment. */ - -static void -optimize_assignment (gfc_code * c) -{ - gfc_expr *lhs, *rhs; - - lhs = c->expr1; - rhs = c->expr2; - - if (lhs->ts.type == BT_CHARACTER && !lhs->ts.deferred) - { - /* Optimize a = trim(b) to a = b. */ - remove_trim (rhs); - - /* Replace a = ' ' by a = '' to optimize away a memcpy. */ - if (is_empty_string (rhs)) - rhs->value.character.length = 0; - } - - if (lhs->rank > 0 && gfc_check_dependency (lhs, rhs, true) == 0) - optimize_binop_array_assignment (c, &rhs, false); -} - - -/* Remove an unneeded function call, modifying the expression. - This replaces the function call with the value of its - first argument. The rest of the argument list is freed. */ - -static void -strip_function_call (gfc_expr *e) -{ - gfc_expr *e1; - gfc_actual_arglist *a; - - a = e->value.function.actual; - - /* We should have at least one argument. */ - gcc_assert (a->expr != NULL); - - e1 = a->expr; - - /* Free the remaining arglist, if any. */ - if (a->next) - gfc_free_actual_arglist (a->next); - - /* Graft the argument expression onto the original function. */ - *e = *e1; - free (e1); - -} - -/* Optimization of lexical comparison functions. */ - -static bool -optimize_lexical_comparison (gfc_expr *e) -{ - if (e->expr_type != EXPR_FUNCTION || e->value.function.isym == NULL) - return false; - - switch (e->value.function.isym->id) - { - case GFC_ISYM_LLE: - return optimize_comparison (e, INTRINSIC_LE); - - case GFC_ISYM_LGE: - return optimize_comparison (e, INTRINSIC_GE); - - case GFC_ISYM_LGT: - return optimize_comparison (e, INTRINSIC_GT); - - case GFC_ISYM_LLT: - return optimize_comparison (e, INTRINSIC_LT); - - default: - break; - } - return false; -} - -/* Combine stuff like [a]>b into [a>b], for easier optimization later. Do not - do CHARACTER because of possible pessimization involving character - lengths. */ - -static bool -combine_array_constructor (gfc_expr *e) -{ - - gfc_expr *op1, *op2; - gfc_expr *scalar; - gfc_expr *new_expr; - gfc_constructor *c, *new_c; - gfc_constructor_base oldbase, newbase; - bool scalar_first; - int n_elem; - bool all_const; - - /* Array constructors have rank one. */ - if (e->rank != 1) - return false; - - /* Don't try to combine association lists, this makes no sense - and leads to an ICE. */ - if (in_assoc_list) - return false; - - /* With FORALL, the BLOCKS created by create_var will cause an ICE. */ - if (forall_level > 0) - return false; - - /* Inside an iterator, things can get hairy; we are likely to create - an invalid temporary variable. */ - if (iterator_level > 0) - return false; - - /* WHERE also doesn't work. */ - if (in_where > 0) - return false; - - op1 = e->value.op.op1; - op2 = e->value.op.op2; - - if (!op1 || !op2) - return false; - - if (op1->expr_type == EXPR_ARRAY && op2->rank == 0) - scalar_first = false; - else if (op2->expr_type == EXPR_ARRAY && op1->rank == 0) - { - scalar_first = true; - op1 = e->value.op.op2; - op2 = e->value.op.op1; - } - else - return false; - - if (op2->ts.type == BT_CHARACTER) - return false; - - /* This might be an expanded constructor with very many constant values. If - we perform the operation here, we might end up with a long compile time - and actually longer execution time, so a length bound is in order here. - If the constructor constains something which is not a constant, it did - not come from an expansion, so leave it alone. */ - -#define CONSTR_LEN_MAX 4 - - oldbase = op1->value.constructor; - - n_elem = 0; - all_const = true; - for (c = gfc_constructor_first (oldbase); c; c = gfc_constructor_next(c)) - { - if (c->expr->expr_type != EXPR_CONSTANT) - { - all_const = false; - break; - } - n_elem += 1; - } - - if (all_const && n_elem > CONSTR_LEN_MAX) - return false; - -#undef CONSTR_LEN_MAX - - newbase = NULL; - e->expr_type = EXPR_ARRAY; - - scalar = create_var (gfc_copy_expr (op2), "constr"); - - for (c = gfc_constructor_first (oldbase); c; - c = gfc_constructor_next (c)) - { - new_expr = gfc_get_expr (); - new_expr->ts = e->ts; - new_expr->expr_type = EXPR_OP; - new_expr->rank = c->expr->rank; - new_expr->where = c->expr->where; - new_expr->value.op.op = e->value.op.op; - - if (scalar_first) - { - new_expr->value.op.op1 = gfc_copy_expr (scalar); - new_expr->value.op.op2 = gfc_copy_expr (c->expr); - } - else - { - new_expr->value.op.op1 = gfc_copy_expr (c->expr); - new_expr->value.op.op2 = gfc_copy_expr (scalar); - } - - new_c = gfc_constructor_append_expr (&newbase, new_expr, &(e->where)); - new_c->iterator = c->iterator; - c->iterator = NULL; - } - - gfc_free_expr (op1); - gfc_free_expr (op2); - gfc_free_expr (scalar); - - e->value.constructor = newbase; - return true; -} - -/* Recursive optimization of operators. */ - -static bool -optimize_op (gfc_expr *e) -{ - bool changed; - - gfc_intrinsic_op op = e->value.op.op; - - changed = false; - - /* Only use new-style comparisons. */ - switch(op) - { - case INTRINSIC_EQ_OS: - op = INTRINSIC_EQ; - break; - - case INTRINSIC_GE_OS: - op = INTRINSIC_GE; - break; - - case INTRINSIC_LE_OS: - op = INTRINSIC_LE; - break; - - case INTRINSIC_NE_OS: - op = INTRINSIC_NE; - break; - - case INTRINSIC_GT_OS: - op = INTRINSIC_GT; - break; - - case INTRINSIC_LT_OS: - op = INTRINSIC_LT; - break; - - default: - break; - } - - switch (op) - { - case INTRINSIC_EQ: - case INTRINSIC_GE: - case INTRINSIC_LE: - case INTRINSIC_NE: - case INTRINSIC_GT: - case INTRINSIC_LT: - changed = optimize_comparison (e, op); - - gcc_fallthrough (); - /* Look at array constructors. */ - case INTRINSIC_PLUS: - case INTRINSIC_MINUS: - case INTRINSIC_TIMES: - case INTRINSIC_DIVIDE: - return combine_array_constructor (e) || changed; - - default: - break; - } - - return false; -} - - -/* Return true if a constant string contains only blanks. */ - -static bool -is_empty_string (gfc_expr *e) -{ - int i; - - if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_CONSTANT) - return false; - - for (i=0; i < e->value.character.length; i++) - { - if (e->value.character.string[i] != ' ') - return false; - } - - return true; -} - - -/* Insert a call to the intrinsic len_trim. Use a different name for - the symbol tree so we don't run into trouble when the user has - renamed len_trim for some reason. */ - -static gfc_expr* -get_len_trim_call (gfc_expr *str, int kind) -{ - gfc_expr *fcn; - gfc_actual_arglist *actual_arglist, *next; - - fcn = gfc_get_expr (); - fcn->expr_type = EXPR_FUNCTION; - fcn->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LEN_TRIM); - actual_arglist = gfc_get_actual_arglist (); - actual_arglist->expr = str; - next = gfc_get_actual_arglist (); - next->expr = gfc_get_int_expr (gfc_default_integer_kind, NULL, kind); - actual_arglist->next = next; - - fcn->value.function.actual = actual_arglist; - fcn->where = str->where; - fcn->ts.type = BT_INTEGER; - fcn->ts.kind = gfc_charlen_int_kind; - - gfc_get_sym_tree ("__internal_len_trim", current_ns, &fcn->symtree, false); - fcn->symtree->n.sym->ts = fcn->ts; - fcn->symtree->n.sym->attr.flavor = FL_PROCEDURE; - fcn->symtree->n.sym->attr.function = 1; - fcn->symtree->n.sym->attr.elemental = 1; - fcn->symtree->n.sym->attr.referenced = 1; - fcn->symtree->n.sym->attr.access = ACCESS_PRIVATE; - gfc_commit_symbol (fcn->symtree->n.sym); - - return fcn; -} - - -/* Optimize expressions for equality. */ - -static bool -optimize_comparison (gfc_expr *e, gfc_intrinsic_op op) -{ - gfc_expr *op1, *op2; - bool change; - int eq; - bool result; - gfc_actual_arglist *firstarg, *secondarg; - - if (e->expr_type == EXPR_OP) - { - firstarg = NULL; - secondarg = NULL; - op1 = e->value.op.op1; - op2 = e->value.op.op2; - } - else if (e->expr_type == EXPR_FUNCTION) - { - /* One of the lexical comparison functions. */ - firstarg = e->value.function.actual; - secondarg = firstarg->next; - op1 = firstarg->expr; - op2 = secondarg->expr; - } - else - gcc_unreachable (); - - /* Strip off unneeded TRIM calls from string comparisons. */ - - change = remove_trim (op1); - - if (remove_trim (op2)) - change = true; - - /* An expression of type EXPR_CONSTANT is only valid for scalars. */ - /* TODO: A scalar constant may be acceptable in some cases (the scalarizer - handles them well). However, there are also cases that need a non-scalar - argument. For example the any intrinsic. See PR 45380. */ - if (e->rank > 0) - return change; - - /* Replace a == '' with len_trim(a) == 0 and a /= '' with - len_trim(a) != 0 */ - if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER - && (op == INTRINSIC_EQ || op == INTRINSIC_NE)) - { - bool empty_op1, empty_op2; - empty_op1 = is_empty_string (op1); - empty_op2 = is_empty_string (op2); - - if (empty_op1 || empty_op2) - { - gfc_expr *fcn; - gfc_expr *zero; - gfc_expr *str; - - /* This can only happen when an error for comparing - characters of different kinds has already been issued. */ - if (empty_op1 && empty_op2) - return false; - - zero = gfc_get_int_expr (gfc_charlen_int_kind, &e->where, 0); - str = empty_op1 ? op2 : op1; - - fcn = get_len_trim_call (str, gfc_charlen_int_kind); - - - if (empty_op1) - gfc_free_expr (op1); - else - gfc_free_expr (op2); - - op1 = fcn; - op2 = zero; - e->value.op.op1 = fcn; - e->value.op.op2 = zero; - } - } - - - /* Don't compare REAL or COMPLEX expressions when honoring NaNs. */ - - if (flag_finite_math_only - || (op1->ts.type != BT_REAL && op2->ts.type != BT_REAL - && op1->ts.type != BT_COMPLEX && op2->ts.type != BT_COMPLEX)) - { - eq = gfc_dep_compare_expr (op1, op2); - if (eq <= -2) - { - /* Replace A // B < A // C with B < C, and A // B < C // B - with A < C. */ - if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER - && op1->expr_type == EXPR_OP - && op1->value.op.op == INTRINSIC_CONCAT - && op2->expr_type == EXPR_OP - && op2->value.op.op == INTRINSIC_CONCAT) - { - gfc_expr *op1_left = op1->value.op.op1; - gfc_expr *op2_left = op2->value.op.op1; - gfc_expr *op1_right = op1->value.op.op2; - gfc_expr *op2_right = op2->value.op.op2; - - if (gfc_dep_compare_expr (op1_left, op2_left) == 0) - { - /* Watch out for 'A ' // x vs. 'A' // x. */ - - if (op1_left->expr_type == EXPR_CONSTANT - && op2_left->expr_type == EXPR_CONSTANT - && op1_left->value.character.length - != op2_left->value.character.length) - return change; - else - { - free (op1_left); - free (op2_left); - if (firstarg) - { - firstarg->expr = op1_right; - secondarg->expr = op2_right; - } - else - { - e->value.op.op1 = op1_right; - e->value.op.op2 = op2_right; - } - optimize_comparison (e, op); - return true; - } - } - if (gfc_dep_compare_expr (op1_right, op2_right) == 0) - { - free (op1_right); - free (op2_right); - if (firstarg) - { - firstarg->expr = op1_left; - secondarg->expr = op2_left; - } - else - { - e->value.op.op1 = op1_left; - e->value.op.op2 = op2_left; - } - - optimize_comparison (e, op); - return true; - } - } - } - else - { - /* eq can only be -1, 0 or 1 at this point. */ - switch (op) - { - case INTRINSIC_EQ: - result = eq == 0; - break; - - case INTRINSIC_GE: - result = eq >= 0; - break; - - case INTRINSIC_LE: - result = eq <= 0; - break; - - case INTRINSIC_NE: - result = eq != 0; - break; - - case INTRINSIC_GT: - result = eq > 0; - break; - - case INTRINSIC_LT: - result = eq < 0; - break; - - default: - gfc_internal_error ("illegal OP in optimize_comparison"); - break; - } - - /* Replace the expression by a constant expression. The typespec - and where remains the way it is. */ - free (op1); - free (op2); - e->expr_type = EXPR_CONSTANT; - e->value.logical = result; - return true; - } - } - - return change; -} - -/* Optimize a trim function by replacing it with an equivalent substring - involving a call to len_trim. This only works for expressions where - variables are trimmed. Return true if anything was modified. */ - -static bool -optimize_trim (gfc_expr *e) -{ - gfc_expr *a; - gfc_ref *ref; - gfc_expr *fcn; - gfc_ref **rr = NULL; - - /* Don't do this optimization within an argument list, because - otherwise aliasing issues may occur. */ - - if (count_arglist != 1) - return false; - - if (e->ts.type != BT_CHARACTER || e->expr_type != EXPR_FUNCTION - || e->value.function.isym == NULL - || e->value.function.isym->id != GFC_ISYM_TRIM) - return false; - - a = e->value.function.actual->expr; - - if (a->expr_type != EXPR_VARIABLE) - return false; - - /* This would pessimize the idiom a = trim(a) for reallocatable strings. */ - - if (a->symtree->n.sym->attr.allocatable) - return false; - - /* Follow all references to find the correct place to put the newly - created reference. FIXME: Also handle substring references and - array references. Array references cause strange regressions at - the moment. */ - - if (a->ref) - { - for (rr = &(a->ref); *rr; rr = &((*rr)->next)) - { - if ((*rr)->type == REF_SUBSTRING || (*rr)->type == REF_ARRAY) - return false; - } - } - - strip_function_call (e); - - if (e->ref == NULL) - rr = &(e->ref); - - /* Create the reference. */ - - ref = gfc_get_ref (); - ref->type = REF_SUBSTRING; - - /* Set the start of the reference. */ - - ref->u.ss.start = gfc_get_int_expr (gfc_charlen_int_kind, NULL, 1); - - /* Build the function call to len_trim(x, gfc_default_integer_kind). */ - - fcn = get_len_trim_call (gfc_copy_expr (e), gfc_charlen_int_kind); - - /* Set the end of the reference to the call to len_trim. */ - - ref->u.ss.end = fcn; - gcc_assert (rr != NULL && *rr == NULL); - *rr = ref; - return true; -} - -/* Optimize minloc(b), where b is rank 1 array, into - (/ minloc(b, dim=1) /), and similarly for maxloc, - as the latter forms are expanded inline. */ - -static void -optimize_minmaxloc (gfc_expr **e) -{ - gfc_expr *fn = *e; - gfc_actual_arglist *a; - char *name, *p; - - if (fn->rank != 1 - || fn->value.function.actual == NULL - || fn->value.function.actual->expr == NULL - || fn->value.function.actual->expr->rank != 1) - return; - - *e = gfc_get_array_expr (fn->ts.type, fn->ts.kind, &fn->where); - (*e)->shape = fn->shape; - fn->rank = 0; - fn->shape = NULL; - gfc_constructor_append_expr (&(*e)->value.constructor, fn, &fn->where); - - name = XALLOCAVEC (char, strlen (fn->value.function.name) + 1); - strcpy (name, fn->value.function.name); - p = strstr (name, "loc0"); - p[3] = '1'; - fn->value.function.name = gfc_get_string ("%s", name); - if (fn->value.function.actual->next) - { - a = fn->value.function.actual->next; - gcc_assert (a->expr == NULL); - } - else - { - a = gfc_get_actual_arglist (); - fn->value.function.actual->next = a; - } - a->expr = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind, - &fn->where); - mpz_set_ui (a->expr->value.integer, 1); -} - -/* Data package to hand down for DO loop checks in a contained - procedure. */ -typedef struct contained_info -{ - gfc_symbol *do_var; - gfc_symbol *procedure; - locus where_do; -} contained_info; - -static enum gfc_exec_op last_io_op; - -/* Callback function to check for INTENT(OUT) and INTENT(INOUT) in a - contained function call. */ - -static int -doloop_contained_function_call (gfc_expr **e, - int *walk_subtrees ATTRIBUTE_UNUSED, void *data) -{ - gfc_expr *expr = *e; - gfc_formal_arglist *f; - gfc_actual_arglist *a; - gfc_symbol *sym, *do_var; - contained_info *info; - - if (expr->expr_type != EXPR_FUNCTION || expr->value.function.isym - || expr->value.function.esym == NULL) - return 0; - - sym = expr->value.function.esym; - f = gfc_sym_get_dummy_args (sym); - if (f == NULL) - return 0; - - info = (contained_info *) data; - do_var = info->do_var; - a = expr->value.function.actual; - - while (a && f) - { - if (a->expr && a->expr->symtree && a->expr->symtree->n.sym == do_var) - { - if (f->sym->attr.intent == INTENT_OUT) - { - gfc_error_now ("Index variable %qs set to undefined as " - "INTENT(OUT) argument at %L in procedure %qs " - "called from within DO loop at %L", do_var->name, - &a->expr->where, info->procedure->name, - &info->where_do); - return 1; - } - else if (f->sym->attr.intent == INTENT_INOUT) - { - gfc_error_now ("Index variable %qs not definable as " - "INTENT(INOUT) argument at %L in procedure %qs " - "called from within DO loop at %L", do_var->name, - &a->expr->where, info->procedure->name, - &info->where_do); - return 1; - } - } - a = a->next; - f = f->next; - } - return 0; -} - -/* Callback function that goes through the code in a contained - procedure to make sure it does not change a variable in a DO - loop. */ - -static int -doloop_contained_procedure_code (gfc_code **c, - int *walk_subtrees ATTRIBUTE_UNUSED, - void *data) -{ - gfc_code *co = *c; - contained_info *info = (contained_info *) data; - gfc_symbol *do_var = info->do_var; - const char *errmsg = _("Index variable %qs redefined at %L in procedure %qs " - "called from within DO loop at %L"); - static enum gfc_exec_op saved_io_op; - - switch (co->op) - { - case EXEC_ASSIGN: - if (co->expr1->symtree && co->expr1->symtree->n.sym == do_var) - gfc_error_now (errmsg, do_var->name, &co->loc, info->procedure->name, - &info->where_do); - break; - - case EXEC_DO: - if (co->ext.iterator && co->ext.iterator->var - && co->ext.iterator->var->symtree->n.sym == do_var) - gfc_error (errmsg, do_var->name, &co->loc, info->procedure->name, - &info->where_do); - break; - - case EXEC_READ: - case EXEC_WRITE: - case EXEC_INQUIRE: - case EXEC_IOLENGTH: - saved_io_op = last_io_op; - last_io_op = co->op; - break; - - case EXEC_OPEN: - if (co->ext.open && co->ext.open->iostat - && co->ext.open->iostat->symtree->n.sym == do_var) - gfc_error_now (errmsg, do_var->name, &co->ext.open->iostat->where, - info->procedure->name, &info->where_do); - break; - - case EXEC_CLOSE: - if (co->ext.close && co->ext.close->iostat - && co->ext.close->iostat->symtree->n.sym == do_var) - gfc_error_now (errmsg, do_var->name, &co->ext.close->iostat->where, - info->procedure->name, &info->where_do); - break; - - case EXEC_TRANSFER: - switch (last_io_op) - { - - case EXEC_INQUIRE: -#define CHECK_INQ(a) do { if (co->ext.inquire && \ - co->ext.inquire->a && \ - co->ext.inquire->a->symtree->n.sym == do_var) \ - gfc_error_now (errmsg, do_var->name, \ - &co->ext.inquire->a->where, \ - info->procedure->name, \ - &info->where_do); \ - } while (0) - - CHECK_INQ(iostat); - CHECK_INQ(number); - CHECK_INQ(position); - CHECK_INQ(recl); - CHECK_INQ(position); - CHECK_INQ(iolength); - CHECK_INQ(strm_pos); - break; -#undef CHECK_INQ - - case EXEC_READ: - if (co->expr1 && co->expr1->symtree - && co->expr1->symtree->n.sym == do_var) - gfc_error_now (errmsg, do_var->name, &co->expr1->where, - info->procedure->name, &info->where_do); - - /* Fallthrough. */ - - case EXEC_WRITE: - if (co->ext.dt && co->ext.dt->iostat && co->ext.dt->iostat->symtree - && co->ext.dt->iostat->symtree->n.sym == do_var) - gfc_error_now (errmsg, do_var->name, &co->ext.dt->iostat->where, - info->procedure->name, &info->where_do); - break; - - case EXEC_IOLENGTH: - if (co->expr1 && co->expr1->symtree - && co->expr1->symtree->n.sym == do_var) - gfc_error_now (errmsg, do_var->name, &co->expr1->where, - info->procedure->name, &info->where_do); - break; - - default: - gcc_unreachable (); - } - break; - - case EXEC_DT_END: - last_io_op = saved_io_op; - break; - - case EXEC_CALL: - gfc_formal_arglist *f; - gfc_actual_arglist *a; - - f = gfc_sym_get_dummy_args (co->resolved_sym); - if (f == NULL) - break; - a = co->ext.actual; - /* Slightly different error message here. If there is an error, - return 1 to avoid an infinite loop. */ - while (a && f) - { - if (a->expr && a->expr->symtree && a->expr->symtree->n.sym == do_var) - { - if (f->sym->attr.intent == INTENT_OUT) - { - gfc_error_now ("Index variable %qs set to undefined as " - "INTENT(OUT) argument at %L in subroutine %qs " - "called from within DO loop at %L", - do_var->name, &a->expr->where, - info->procedure->name, &info->where_do); - return 1; - } - else if (f->sym->attr.intent == INTENT_INOUT) - { - gfc_error_now ("Index variable %qs not definable as " - "INTENT(INOUT) argument at %L in subroutine %qs " - "called from within DO loop at %L", do_var->name, - &a->expr->where, info->procedure->name, - &info->where_do); - return 1; - } - } - a = a->next; - f = f->next; - } - break; - default: - break; - } - return 0; -} - -/* Callback function for code checking that we do not pass a DO variable to an - INTENT(OUT) or INTENT(INOUT) dummy variable. */ - -static int -doloop_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - gfc_code *co; - int i; - gfc_formal_arglist *f; - gfc_actual_arglist *a; - gfc_code *cl; - do_t loop, *lp; - bool seen_goto; - - co = *c; - - /* If the doloop_list grew, we have to truncate it here. */ - - if ((unsigned) doloop_level < doloop_list.length()) - doloop_list.truncate (doloop_level); - - seen_goto = false; - switch (co->op) - { - case EXEC_DO: - - if (co->ext.iterator && co->ext.iterator->var) - loop.c = co; - else - loop.c = NULL; - - loop.branch_level = if_level + select_level; - loop.seen_goto = false; - doloop_list.safe_push (loop); - break; - - /* If anything could transfer control away from a suspicious - subscript, make sure to set seen_goto in the current DO loop - (if any). */ - case EXEC_GOTO: - case EXEC_EXIT: - case EXEC_STOP: - case EXEC_ERROR_STOP: - case EXEC_CYCLE: - seen_goto = true; - break; - - case EXEC_OPEN: - if (co->ext.open->err) - seen_goto = true; - break; - - case EXEC_CLOSE: - if (co->ext.close->err) - seen_goto = true; - break; - - case EXEC_BACKSPACE: - case EXEC_ENDFILE: - case EXEC_REWIND: - case EXEC_FLUSH: - - if (co->ext.filepos->err) - seen_goto = true; - break; - - case EXEC_INQUIRE: - if (co->ext.filepos->err) - seen_goto = true; - break; - - case EXEC_READ: - case EXEC_WRITE: - if (co->ext.dt->err || co->ext.dt->end || co->ext.dt->eor) - seen_goto = true; - break; - - case EXEC_WAIT: - if (co->ext.wait->err || co->ext.wait->end || co->ext.wait->eor) - loop.seen_goto = true; - break; - - case EXEC_CALL: - if (co->resolved_sym == NULL) - break; - - /* Test if somebody stealthily changes the DO variable from - under us by changing it in a host-associated procedure. */ - if (co->resolved_sym->attr.contained) - { - FOR_EACH_VEC_ELT (doloop_list, i, lp) - { - gfc_symbol *sym = co->resolved_sym; - contained_info info; - gfc_namespace *ns; - - cl = lp->c; - info.do_var = cl->ext.iterator->var->symtree->n.sym; - info.procedure = co->resolved_sym; /* sym? */ - info.where_do = co->loc; - /* Look contained procedures under the namespace of the - variable. */ - for (ns = info.do_var->ns->contained; ns; ns = ns->sibling) - if (ns->proc_name && ns->proc_name == sym) - gfc_code_walker (&ns->code, doloop_contained_procedure_code, - doloop_contained_function_call, &info); - } - } - - f = gfc_sym_get_dummy_args (co->resolved_sym); - - /* Withot a formal arglist, there is only unknown INTENT, - which we don't check for. */ - if (f == NULL) - break; - - a = co->ext.actual; - - while (a && f) - { - FOR_EACH_VEC_ELT (doloop_list, i, lp) - { - gfc_symbol *do_sym; - cl = lp->c; - - if (cl == NULL) - break; - - do_sym = cl->ext.iterator->var->symtree->n.sym; - - if (a->expr && a->expr->symtree && f->sym - && a->expr->symtree->n.sym == do_sym) - { - if (f->sym->attr.intent == INTENT_OUT) - gfc_error_now ("Variable %qs at %L set to undefined " - "value inside loop beginning at %L as " - "INTENT(OUT) argument to subroutine %qs", - do_sym->name, &a->expr->where, - &(doloop_list[i].c->loc), - co->symtree->n.sym->name); - else if (f->sym->attr.intent == INTENT_INOUT) - gfc_error_now ("Variable %qs at %L not definable inside " - "loop beginning at %L as INTENT(INOUT) " - "argument to subroutine %qs", - do_sym->name, &a->expr->where, - &(doloop_list[i].c->loc), - co->symtree->n.sym->name); - } - } - a = a->next; - f = f->next; - } - - break; - - default: - break; - } - if (seen_goto && doloop_level > 0) - doloop_list[doloop_level-1].seen_goto = true; - - return 0; -} - -/* Callback function to warn about different things within DO loops. */ - -static int -do_function (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - do_t *last; - - if (doloop_list.length () == 0) - return 0; - - if ((*e)->expr_type == EXPR_FUNCTION) - do_intent (e); - - last = &doloop_list.last(); - if (last->seen_goto && !warn_do_subscript) - return 0; - - if ((*e)->expr_type == EXPR_VARIABLE) - do_subscript (e); - - return 0; -} - -typedef struct -{ - gfc_symbol *sym; - mpz_t val; -} insert_index_t; - -/* Callback function - if the expression is the variable in data->sym, - replace it with a constant from data->val. */ - -static int -callback_insert_index (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data) -{ - insert_index_t *d; - gfc_expr *ex, *n; - - ex = (*e); - if (ex->expr_type != EXPR_VARIABLE) - return 0; - - d = (insert_index_t *) data; - if (ex->symtree->n.sym != d->sym) - return 0; - - n = gfc_get_constant_expr (BT_INTEGER, ex->ts.kind, &ex->where); - mpz_set (n->value.integer, d->val); - - gfc_free_expr (ex); - *e = n; - return 0; -} - -/* In the expression e, replace occurrences of the variable sym with - val. If this results in a constant expression, return true and - return the value in ret. Return false if the expression already - is a constant. Caller has to clear ret in that case. */ - -static bool -insert_index (gfc_expr *e, gfc_symbol *sym, mpz_t val, mpz_t ret) -{ - gfc_expr *n; - insert_index_t data; - bool rc; - - if (e->expr_type == EXPR_CONSTANT) - return false; - - n = gfc_copy_expr (e); - data.sym = sym; - mpz_init_set (data.val, val); - gfc_expr_walker (&n, callback_insert_index, (void *) &data); - - /* Suppress errors here - we could get errors here such as an - out of bounds access for arrays, see PR 90563. */ - gfc_push_suppress_errors (); - gfc_simplify_expr (n, 0); - gfc_pop_suppress_errors (); - - if (n->expr_type == EXPR_CONSTANT) - { - rc = true; - mpz_init_set (ret, n->value.integer); - } - else - rc = false; - - mpz_clear (data.val); - gfc_free_expr (n); - return rc; - -} - -/* Check array subscripts for possible out-of-bounds accesses in DO - loops with constant bounds. */ - -static int -do_subscript (gfc_expr **e) -{ - gfc_expr *v; - gfc_array_ref *ar; - gfc_ref *ref; - int i,j; - gfc_code *dl; - do_t *lp; - - v = *e; - /* Constants are already checked. */ - if (v->expr_type == EXPR_CONSTANT) - return 0; - - /* Wrong warnings will be generated in an associate list. */ - if (in_assoc_list) - return 0; - - /* We already warned about this. */ - if (v->do_not_warn) - return 0; - - v->do_not_warn = 1; - - for (ref = v->ref; ref; ref = ref->next) - { - if (ref->type == REF_ARRAY && ref->u.ar.type == AR_ELEMENT) - { - ar = & ref->u.ar; - FOR_EACH_VEC_ELT (doloop_list, j, lp) - { - gfc_symbol *do_sym; - mpz_t do_start, do_step, do_end; - bool have_do_start, have_do_end; - bool error_not_proven; - int warn; - int sgn; - - dl = lp->c; - if (dl == NULL) - break; - - /* If we are within a branch, or a goto or equivalent - was seen in the DO loop before, then we cannot prove that - this expression is actually evaluated. Don't do anything - unless we want to see it all. */ - error_not_proven = lp->seen_goto - || lp->branch_level < if_level + select_level; - - if (error_not_proven && !warn_do_subscript) - break; - - if (error_not_proven) - warn = OPT_Wdo_subscript; - else - warn = 0; - - do_sym = dl->ext.iterator->var->symtree->n.sym; - if (do_sym->ts.type != BT_INTEGER) - continue; - - /* If we do not know about the stepsize, the loop may be zero trip. - Do not warn in this case. */ - - if (dl->ext.iterator->step->expr_type == EXPR_CONSTANT) - { - sgn = mpz_cmp_ui (dl->ext.iterator->step->value.integer, 0); - /* This can happen, but then the error has been - reported previously. */ - if (sgn == 0) - continue; - - mpz_init_set (do_step, dl->ext.iterator->step->value.integer); - } - - else - continue; - - if (dl->ext.iterator->start->expr_type == EXPR_CONSTANT) - { - have_do_start = true; - mpz_init_set (do_start, dl->ext.iterator->start->value.integer); - } - else - have_do_start = false; - - if (dl->ext.iterator->end->expr_type == EXPR_CONSTANT) - { - have_do_end = true; - mpz_init_set (do_end, dl->ext.iterator->end->value.integer); - } - else - have_do_end = false; - - if (!have_do_start && !have_do_end) - return 0; - - /* No warning inside a zero-trip loop. */ - if (have_do_start && have_do_end) - { - int cmp; - - cmp = mpz_cmp (do_end, do_start); - if ((sgn > 0 && cmp < 0) || (sgn < 0 && cmp > 0)) - break; - } - - /* May have to correct the end value if the step does not equal - one. */ - if (have_do_start && have_do_end && mpz_cmp_ui (do_step, 1) != 0) - { - mpz_t diff, rem; - - mpz_init (diff); - mpz_init (rem); - mpz_sub (diff, do_end, do_start); - mpz_tdiv_r (rem, diff, do_step); - mpz_sub (do_end, do_end, rem); - mpz_clear (diff); - mpz_clear (rem); - } - - for (i = 0; i< ar->dimen; i++) - { - mpz_t val; - if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_start - && insert_index (ar->start[i], do_sym, do_start, val)) - { - if (ar->as->lower[i] - && ar->as->lower[i]->expr_type == EXPR_CONSTANT - && ar->as->lower[i]->ts.type == BT_INTEGER - && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0) - gfc_warning (warn, "Array reference at %L out of bounds " - "(%ld < %ld) in loop beginning at %L", - &ar->start[i]->where, mpz_get_si (val), - mpz_get_si (ar->as->lower[i]->value.integer), - &doloop_list[j].c->loc); - - if (ar->as->upper[i] - && ar->as->upper[i]->expr_type == EXPR_CONSTANT - && ar->as->upper[i]->ts.type == BT_INTEGER - && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0) - gfc_warning (warn, "Array reference at %L out of bounds " - "(%ld > %ld) in loop beginning at %L", - &ar->start[i]->where, mpz_get_si (val), - mpz_get_si (ar->as->upper[i]->value.integer), - &doloop_list[j].c->loc); - - mpz_clear (val); - } - - if (ar->dimen_type[i] == DIMEN_ELEMENT && have_do_end - && insert_index (ar->start[i], do_sym, do_end, val)) - { - if (ar->as->lower[i] - && ar->as->lower[i]->expr_type == EXPR_CONSTANT - && ar->as->lower[i]->ts.type == BT_INTEGER - && mpz_cmp (val, ar->as->lower[i]->value.integer) < 0) - gfc_warning (warn, "Array reference at %L out of bounds " - "(%ld < %ld) in loop beginning at %L", - &ar->start[i]->where, mpz_get_si (val), - mpz_get_si (ar->as->lower[i]->value.integer), - &doloop_list[j].c->loc); - - if (ar->as->upper[i] - && ar->as->upper[i]->expr_type == EXPR_CONSTANT - && ar->as->upper[i]->ts.type == BT_INTEGER - && mpz_cmp (val, ar->as->upper[i]->value.integer) > 0) - gfc_warning (warn, "Array reference at %L out of bounds " - "(%ld > %ld) in loop beginning at %L", - &ar->start[i]->where, mpz_get_si (val), - mpz_get_si (ar->as->upper[i]->value.integer), - &doloop_list[j].c->loc); - - mpz_clear (val); - } - } - } - } - } - return 0; -} -/* Function for functions checking that we do not pass a DO variable - to an INTENT(OUT) or INTENT(INOUT) dummy variable. */ - -static int -do_intent (gfc_expr **e) -{ - gfc_formal_arglist *f; - gfc_actual_arglist *a; - gfc_expr *expr; - gfc_code *dl; - do_t *lp; - int i; - gfc_symbol *sym; - - expr = *e; - if (expr->expr_type != EXPR_FUNCTION) - return 0; - - /* Intrinsic functions don't modify their arguments. */ - - if (expr->value.function.isym) - return 0; - - sym = expr->value.function.esym; - if (sym == NULL) - return 0; - - if (sym->attr.contained) - { - FOR_EACH_VEC_ELT (doloop_list, i, lp) - { - contained_info info; - gfc_namespace *ns; - - dl = lp->c; - info.do_var = dl->ext.iterator->var->symtree->n.sym; - info.procedure = sym; - info.where_do = expr->where; - /* Look contained procedures under the namespace of the - variable. */ - for (ns = info.do_var->ns->contained; ns; ns = ns->sibling) - if (ns->proc_name && ns->proc_name == sym) - gfc_code_walker (&ns->code, doloop_contained_procedure_code, - dummy_expr_callback, &info); - } - } - - f = gfc_sym_get_dummy_args (sym); - - /* Without a formal arglist, there is only unknown INTENT, - which we don't check for. */ - if (f == NULL) - return 0; - - a = expr->value.function.actual; - - while (a && f) - { - FOR_EACH_VEC_ELT (doloop_list, i, lp) - { - gfc_symbol *do_sym; - dl = lp->c; - if (dl == NULL) - break; - - do_sym = dl->ext.iterator->var->symtree->n.sym; - - if (a->expr && a->expr->symtree - && a->expr->symtree->n.sym == do_sym) - { - if (f->sym->attr.intent == INTENT_OUT) - gfc_error_now ("Variable %qs at %L set to undefined value " - "inside loop beginning at %L as INTENT(OUT) " - "argument to function %qs", do_sym->name, - &a->expr->where, &doloop_list[i].c->loc, - expr->symtree->n.sym->name); - else if (f->sym->attr.intent == INTENT_INOUT) - gfc_error_now ("Variable %qs at %L not definable inside loop" - " beginning at %L as INTENT(INOUT) argument to" - " function %qs", do_sym->name, - &a->expr->where, &doloop_list[i].c->loc, - expr->symtree->n.sym->name); - } - } - a = a->next; - f = f->next; - } - - return 0; -} - -static void -doloop_warn (gfc_namespace *ns) -{ - gfc_code_walker (&ns->code, doloop_code, do_function, NULL); - - for (ns = ns->contained; ns; ns = ns->sibling) - { - if (ns->code == NULL || ns->code->op != EXEC_BLOCK) - doloop_warn (ns); - } -} - -/* This selction deals with inlining calls to MATMUL. */ - -/* Replace calls to matmul outside of straight assignments with a temporary - variable so that later inlining will work. */ - -static int -matmul_to_var_expr (gfc_expr **ep, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data) -{ - gfc_expr *e, *n; - bool *found = (bool *) data; - - e = *ep; - - if (e->expr_type != EXPR_FUNCTION - || e->value.function.isym == NULL - || e->value.function.isym->id != GFC_ISYM_MATMUL) - return 0; - - if (forall_level > 0 || iterator_level > 0 || in_omp_workshare - || in_omp_atomic || in_where || in_assoc_list) - return 0; - - /* Check if this is already in the form c = matmul(a,b). */ - - if ((*current_code)->expr2 == e) - return 0; - - n = create_var (e, "matmul"); - - /* If create_var is unable to create a variable (for example if - -fno-realloc-lhs is in force with a variable that does not have bounds - known at compile-time), just return. */ - - if (n == NULL) - return 0; - - *ep = n; - *found = true; - return 0; -} - -/* Set current_code and associated variables so that matmul_to_var_expr can - work. */ - -static int -matmul_to_var_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - if (current_code != c) - { - current_code = c; - inserted_block = NULL; - changed_statement = NULL; - } - - return 0; -} - - -/* Take a statement of the shape c = matmul(a,b) and create temporaries - for a and b if there is a dependency between the arguments and the - result variable or if a or b are the result of calculations that cannot - be handled by the inliner. */ - -static int -matmul_temp_args (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - gfc_expr *expr1, *expr2; - gfc_code *co; - gfc_actual_arglist *a, *b; - bool a_tmp, b_tmp; - gfc_expr *matrix_a, *matrix_b; - bool conjg_a, conjg_b, transpose_a, transpose_b; - - co = *c; - - if (co->op != EXEC_ASSIGN) - return 0; - - if (forall_level > 0 || iterator_level > 0 || in_omp_workshare - || in_omp_atomic || in_where) - return 0; - - /* This has some duplication with inline_matmul_assign. This - is because the creation of temporary variables could still fail, - and inline_matmul_assign still needs to be able to handle these - cases. */ - expr1 = co->expr1; - expr2 = co->expr2; - - if (expr2->expr_type != EXPR_FUNCTION - || expr2->value.function.isym == NULL - || expr2->value.function.isym->id != GFC_ISYM_MATMUL) - return 0; - - a_tmp = false; - a = expr2->value.function.actual; - matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a); - if (matrix_a != NULL) - { - if (matrix_a->expr_type == EXPR_VARIABLE - && (gfc_check_dependency (matrix_a, expr1, true) - || gfc_has_dimen_vector_ref (matrix_a))) - a_tmp = true; - } - else - a_tmp = true; - - b_tmp = false; - b = a->next; - matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b); - if (matrix_b != NULL) - { - if (matrix_b->expr_type == EXPR_VARIABLE - && (gfc_check_dependency (matrix_b, expr1, true) - || gfc_has_dimen_vector_ref (matrix_b))) - b_tmp = true; - } - else - b_tmp = true; - - if (!a_tmp && !b_tmp) - return 0; - - current_code = c; - inserted_block = NULL; - changed_statement = NULL; - if (a_tmp) - { - gfc_expr *at; - at = create_var (a->expr,"mma"); - if (at) - a->expr = at; - } - if (b_tmp) - { - gfc_expr *bt; - bt = create_var (b->expr,"mmb"); - if (bt) - b->expr = bt; - } - return 0; -} - -/* Auxiliary function to build and simplify an array inquiry function. - dim is zero-based. */ - -static gfc_expr * -get_array_inq_function (gfc_isym_id id, gfc_expr *e, int dim, int okind = 0) -{ - gfc_expr *fcn; - gfc_expr *dim_arg, *kind; - const char *name; - gfc_expr *ec; - - switch (id) - { - case GFC_ISYM_LBOUND: - name = "_gfortran_lbound"; - break; - - case GFC_ISYM_UBOUND: - name = "_gfortran_ubound"; - break; - - case GFC_ISYM_SIZE: - name = "_gfortran_size"; - break; - - default: - gcc_unreachable (); - } - - dim_arg = gfc_get_int_expr (gfc_default_integer_kind, &e->where, dim); - if (okind != 0) - kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where, - okind); - else - kind = gfc_get_int_expr (gfc_default_integer_kind, &e->where, - gfc_index_integer_kind); - - ec = gfc_copy_expr (e); - - /* No bounds checking, this will be done before the loops if -fcheck=bounds - is in effect. */ - ec->no_bounds_check = 1; - fcn = gfc_build_intrinsic_call (current_ns, id, name, e->where, 3, - ec, dim_arg, kind); - gfc_simplify_expr (fcn, 0); - fcn->no_bounds_check = 1; - return fcn; -} - -/* Builds a logical expression. */ - -static gfc_expr* -build_logical_expr (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2) -{ - gfc_typespec ts; - gfc_expr *res; - - ts.type = BT_LOGICAL; - ts.kind = gfc_default_logical_kind; - res = gfc_get_expr (); - res->where = e1->where; - res->expr_type = EXPR_OP; - res->value.op.op = op; - res->value.op.op1 = e1; - res->value.op.op2 = e2; - res->ts = ts; - - return res; -} - - -/* Return an operation of one two gfc_expr (one if e2 is NULL). This assumes - compatible typespecs. */ - -static gfc_expr * -get_operand (gfc_intrinsic_op op, gfc_expr *e1, gfc_expr *e2) -{ - gfc_expr *res; - - res = gfc_get_expr (); - res->ts = e1->ts; - res->where = e1->where; - res->expr_type = EXPR_OP; - res->value.op.op = op; - res->value.op.op1 = e1; - res->value.op.op2 = e2; - gfc_simplify_expr (res, 0); - return res; -} - -/* Generate the IF statement for a runtime check if we want to do inlining or - not - putting in the code for both branches and putting it into the syntax - tree is the caller's responsibility. For fixed array sizes, this should be - removed by DCE. Only called for rank-two matrices A and B. */ - -static gfc_code * -inline_limit_check (gfc_expr *a, gfc_expr *b, int limit, int rank_a) -{ - gfc_expr *inline_limit; - gfc_code *if_1, *if_2, *else_2; - gfc_expr *b2, *a2, *a1, *m1, *m2; - gfc_typespec ts; - gfc_expr *cond; - - gcc_assert (rank_a == 1 || rank_a == 2); - - /* Calculation is done in real to avoid integer overflow. */ - - inline_limit = gfc_get_constant_expr (BT_REAL, gfc_default_real_kind, - &a->where); - mpfr_set_si (inline_limit->value.real, limit, GFC_RND_MODE); - - /* Set the limit according to the rank. */ - mpfr_pow_ui (inline_limit->value.real, inline_limit->value.real, rank_a + 1, - GFC_RND_MODE); - - a1 = get_array_inq_function (GFC_ISYM_SIZE, a, 1); - - /* For a_rank = 1, must use one as the size of a along the second - dimension as to avoid too much code duplication. */ - - if (rank_a == 2) - a2 = get_array_inq_function (GFC_ISYM_SIZE, a, 2); - else - a2 = gfc_get_int_expr (gfc_index_integer_kind, &a->where, 1); - - b2 = get_array_inq_function (GFC_ISYM_SIZE, b, 2); - - gfc_clear_ts (&ts); - ts.type = BT_REAL; - ts.kind = gfc_default_real_kind; - gfc_convert_type_warn (a1, &ts, 2, 0); - gfc_convert_type_warn (a2, &ts, 2, 0); - gfc_convert_type_warn (b2, &ts, 2, 0); - - m1 = get_operand (INTRINSIC_TIMES, a1, a2); - m2 = get_operand (INTRINSIC_TIMES, m1, b2); - - cond = build_logical_expr (INTRINSIC_LE, m2, inline_limit); - gfc_simplify_expr (cond, 0); - - else_2 = XCNEW (gfc_code); - else_2->op = EXEC_IF; - else_2->loc = a->where; - - if_2 = XCNEW (gfc_code); - if_2->op = EXEC_IF; - if_2->expr1 = cond; - if_2->loc = a->where; - if_2->block = else_2; - - if_1 = XCNEW (gfc_code); - if_1->op = EXEC_IF; - if_1->block = if_2; - if_1->loc = a->where; - - return if_1; -} - - -/* Insert code to issue a runtime error if the expressions are not equal. */ - -static gfc_code * -runtime_error_ne (gfc_expr *e1, gfc_expr *e2, const char *msg) -{ - gfc_expr *cond; - gfc_code *if_1, *if_2; - gfc_code *c; - gfc_actual_arglist *a1, *a2, *a3; - - gcc_assert (e1->where.lb); - /* Build the call to runtime_error. */ - c = XCNEW (gfc_code); - c->op = EXEC_CALL; - c->loc = e1->where; - - /* Get a null-terminated message string. */ - - a1 = gfc_get_actual_arglist (); - a1->expr = gfc_get_character_expr (gfc_default_character_kind, &e1->where, - msg, strlen(msg)+1); - c->ext.actual = a1; - - /* Pass the value of the first expression. */ - a2 = gfc_get_actual_arglist (); - a2->expr = gfc_copy_expr (e1); - a1->next = a2; - - /* Pass the value of the second expression. */ - a3 = gfc_get_actual_arglist (); - a3->expr = gfc_copy_expr (e2); - a2->next = a3; - - gfc_check_fe_runtime_error (c->ext.actual); - gfc_resolve_fe_runtime_error (c); - - if_2 = XCNEW (gfc_code); - if_2->op = EXEC_IF; - if_2->loc = e1->where; - if_2->next = c; - - if_1 = XCNEW (gfc_code); - if_1->op = EXEC_IF; - if_1->block = if_2; - if_1->loc = e1->where; - - cond = build_logical_expr (INTRINSIC_NE, e1, e2); - gfc_simplify_expr (cond, 0); - if_2->expr1 = cond; - - return if_1; -} - -/* Handle matrix reallocation. Caller is responsible to insert into - the code tree. - - For the two-dimensional case, build - - if (allocated(c)) then - if (size(c,1) /= size(a,1) .or. size(c,2) /= size(b,2)) then - deallocate(c) - allocate (c(size(a,1), size(b,2))) - end if - else - allocate (c(size(a,1),size(b,2))) - end if - - and for the other cases correspondingly. -*/ - -static gfc_code * -matmul_lhs_realloc (gfc_expr *c, gfc_expr *a, gfc_expr *b, - enum matrix_case m_case) -{ - - gfc_expr *allocated, *alloc_expr; - gfc_code *if_alloc_1, *if_alloc_2, *if_size_1, *if_size_2; - gfc_code *else_alloc; - gfc_code *deallocate, *allocate1, *allocate_else; - gfc_array_ref *ar; - gfc_expr *cond, *ne1, *ne2; - - if (warn_realloc_lhs) - gfc_warning (OPT_Wrealloc_lhs, - "Code for reallocating the allocatable array at %L will " - "be added", &c->where); - - alloc_expr = gfc_copy_expr (c); - - ar = gfc_find_array_ref (alloc_expr); - gcc_assert (ar && ar->type == AR_FULL); - - /* c comes in as a full ref. Change it into a copy and make it into an - element ref so it has the right form for ALLOCATE. In the same - switch statement, also generate the size comparison for the secod IF - statement. */ - - ar->type = AR_ELEMENT; - - switch (m_case) - { - case A2B2: - ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1); - ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2); - ne1 = build_logical_expr (INTRINSIC_NE, - get_array_inq_function (GFC_ISYM_SIZE, c, 1), - get_array_inq_function (GFC_ISYM_SIZE, a, 1)); - ne2 = build_logical_expr (INTRINSIC_NE, - get_array_inq_function (GFC_ISYM_SIZE, c, 2), - get_array_inq_function (GFC_ISYM_SIZE, b, 2)); - cond = build_logical_expr (INTRINSIC_OR, ne1, ne2); - break; - - case A2B2T: - ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1); - ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1); - - ne1 = build_logical_expr (INTRINSIC_NE, - get_array_inq_function (GFC_ISYM_SIZE, c, 1), - get_array_inq_function (GFC_ISYM_SIZE, a, 1)); - ne2 = build_logical_expr (INTRINSIC_NE, - get_array_inq_function (GFC_ISYM_SIZE, c, 2), - get_array_inq_function (GFC_ISYM_SIZE, b, 1)); - cond = build_logical_expr (INTRINSIC_OR, ne1, ne2); - break; - - case A2TB2: - - ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2); - ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 2); - - ne1 = build_logical_expr (INTRINSIC_NE, - get_array_inq_function (GFC_ISYM_SIZE, c, 1), - get_array_inq_function (GFC_ISYM_SIZE, a, 2)); - ne2 = build_logical_expr (INTRINSIC_NE, - get_array_inq_function (GFC_ISYM_SIZE, c, 2), - get_array_inq_function (GFC_ISYM_SIZE, b, 2)); - cond = build_logical_expr (INTRINSIC_OR, ne1, ne2); - break; - - case A2B1: - ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 1); - cond = build_logical_expr (INTRINSIC_NE, - get_array_inq_function (GFC_ISYM_SIZE, c, 1), - get_array_inq_function (GFC_ISYM_SIZE, a, 2)); - break; - - case A1B2: - ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, b, 2); - cond = build_logical_expr (INTRINSIC_NE, - get_array_inq_function (GFC_ISYM_SIZE, c, 1), - get_array_inq_function (GFC_ISYM_SIZE, b, 2)); - break; - - case A2TB2T: - /* This can only happen for BLAS, we do not handle that case in - inline mamtul. */ - ar->start[0] = get_array_inq_function (GFC_ISYM_SIZE, a, 2); - ar->start[1] = get_array_inq_function (GFC_ISYM_SIZE, b, 1); - - ne1 = build_logical_expr (INTRINSIC_NE, - get_array_inq_function (GFC_ISYM_SIZE, c, 1), - get_array_inq_function (GFC_ISYM_SIZE, a, 2)); - ne2 = build_logical_expr (INTRINSIC_NE, - get_array_inq_function (GFC_ISYM_SIZE, c, 2), - get_array_inq_function (GFC_ISYM_SIZE, b, 1)); - - cond = build_logical_expr (INTRINSIC_OR, ne1, ne2); - break; - - default: - gcc_unreachable(); - - } - - gfc_simplify_expr (cond, 0); - - /* We need two identical allocate statements in two - branches of the IF statement. */ - - allocate1 = XCNEW (gfc_code); - allocate1->op = EXEC_ALLOCATE; - allocate1->ext.alloc.list = gfc_get_alloc (); - allocate1->loc = c->where; - allocate1->ext.alloc.list->expr = gfc_copy_expr (alloc_expr); - - allocate_else = XCNEW (gfc_code); - allocate_else->op = EXEC_ALLOCATE; - allocate_else->ext.alloc.list = gfc_get_alloc (); - allocate_else->loc = c->where; - allocate_else->ext.alloc.list->expr = alloc_expr; - - allocated = gfc_build_intrinsic_call (current_ns, GFC_ISYM_ALLOCATED, - "_gfortran_allocated", c->where, - 1, gfc_copy_expr (c)); - - deallocate = XCNEW (gfc_code); - deallocate->op = EXEC_DEALLOCATE; - deallocate->ext.alloc.list = gfc_get_alloc (); - deallocate->ext.alloc.list->expr = gfc_copy_expr (c); - deallocate->next = allocate1; - deallocate->loc = c->where; - - if_size_2 = XCNEW (gfc_code); - if_size_2->op = EXEC_IF; - if_size_2->expr1 = cond; - if_size_2->loc = c->where; - if_size_2->next = deallocate; - - if_size_1 = XCNEW (gfc_code); - if_size_1->op = EXEC_IF; - if_size_1->block = if_size_2; - if_size_1->loc = c->where; - - else_alloc = XCNEW (gfc_code); - else_alloc->op = EXEC_IF; - else_alloc->loc = c->where; - else_alloc->next = allocate_else; - - if_alloc_2 = XCNEW (gfc_code); - if_alloc_2->op = EXEC_IF; - if_alloc_2->expr1 = allocated; - if_alloc_2->loc = c->where; - if_alloc_2->next = if_size_1; - if_alloc_2->block = else_alloc; - - if_alloc_1 = XCNEW (gfc_code); - if_alloc_1->op = EXEC_IF; - if_alloc_1->block = if_alloc_2; - if_alloc_1->loc = c->where; - - return if_alloc_1; -} - -/* Callback function for has_function_or_op. */ - -static int -is_function_or_op (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - if ((*e) == 0) - return 0; - else - return (*e)->expr_type == EXPR_FUNCTION - || (*e)->expr_type == EXPR_OP; -} - -/* Returns true if the expression contains a function. */ - -static bool -has_function_or_op (gfc_expr **e) -{ - if (e == NULL) - return false; - else - return gfc_expr_walker (e, is_function_or_op, NULL); -} - -/* Freeze (assign to a temporary variable) a single expression. */ - -static void -freeze_expr (gfc_expr **ep) -{ - gfc_expr *ne; - if (has_function_or_op (ep)) - { - ne = create_var (*ep, "freeze"); - *ep = ne; - } -} - -/* Go through an expression's references and assign them to temporary - variables if they contain functions. This is usually done prior to - front-end scalarization to avoid multiple invocations of functions. */ - -static void -freeze_references (gfc_expr *e) -{ - gfc_ref *r; - gfc_array_ref *ar; - int i; - - for (r=e->ref; r; r=r->next) - { - if (r->type == REF_SUBSTRING) - { - if (r->u.ss.start != NULL) - freeze_expr (&r->u.ss.start); - - if (r->u.ss.end != NULL) - freeze_expr (&r->u.ss.end); - } - else if (r->type == REF_ARRAY) - { - ar = &r->u.ar; - switch (ar->type) - { - case AR_FULL: - break; - - case AR_SECTION: - for (i=0; i<ar->dimen; i++) - { - if (ar->dimen_type[i] == DIMEN_RANGE) - { - freeze_expr (&ar->start[i]); - freeze_expr (&ar->end[i]); - freeze_expr (&ar->stride[i]); - } - else if (ar->dimen_type[i] == DIMEN_ELEMENT) - { - freeze_expr (&ar->start[i]); - } - } - break; - - case AR_ELEMENT: - for (i=0; i<ar->dimen; i++) - freeze_expr (&ar->start[i]); - break; - - default: - break; - } - } - } -} - -/* Convert to gfc_index_integer_kind if needed, just do a copy otherwise. */ - -static gfc_expr * -convert_to_index_kind (gfc_expr *e) -{ - gfc_expr *res; - - gcc_assert (e != NULL); - - res = gfc_copy_expr (e); - - gcc_assert (e->ts.type == BT_INTEGER); - - if (res->ts.kind != gfc_index_integer_kind) - { - gfc_typespec ts; - gfc_clear_ts (&ts); - ts.type = BT_INTEGER; - ts.kind = gfc_index_integer_kind; - - gfc_convert_type_warn (e, &ts, 2, 0); - } - - return res; -} - -/* Function to create a DO loop including creation of the - iteration variable. gfc_expr are copied.*/ - -static gfc_code * -create_do_loop (gfc_expr *start, gfc_expr *end, gfc_expr *step, locus *where, - gfc_namespace *ns, char *vname) -{ - - char name[GFC_MAX_SYMBOL_LEN +1]; - gfc_symtree *symtree; - gfc_symbol *symbol; - gfc_expr *i; - gfc_code *n, *n2; - - /* Create an expression for the iteration variable. */ - if (vname) - sprintf (name, "__var_%d_do_%s", var_num++, vname); - else - sprintf (name, "__var_%d_do", var_num++); - - - if (gfc_get_sym_tree (name, ns, &symtree, false) != 0) - gcc_unreachable (); - - /* Create the loop variable. */ - - symbol = symtree->n.sym; - symbol->ts.type = BT_INTEGER; - symbol->ts.kind = gfc_index_integer_kind; - symbol->attr.flavor = FL_VARIABLE; - symbol->attr.referenced = 1; - symbol->attr.dimension = 0; - symbol->attr.fe_temp = 1; - gfc_commit_symbol (symbol); - - i = gfc_get_expr (); - i->expr_type = EXPR_VARIABLE; - i->ts = symbol->ts; - i->rank = 0; - i->where = *where; - i->symtree = symtree; - - /* ... and the nested DO statements. */ - n = XCNEW (gfc_code); - n->op = EXEC_DO; - n->loc = *where; - n->ext.iterator = gfc_get_iterator (); - n->ext.iterator->var = i; - n->ext.iterator->start = convert_to_index_kind (start); - n->ext.iterator->end = convert_to_index_kind (end); - if (step) - n->ext.iterator->step = convert_to_index_kind (step); - else - n->ext.iterator->step = gfc_get_int_expr (gfc_index_integer_kind, - where, 1); - - n2 = XCNEW (gfc_code); - n2->op = EXEC_DO; - n2->loc = *where; - n2->next = NULL; - n->block = n2; - return n; -} - -/* Get the upper bound of the DO loops for matmul along a dimension. This - is one-based. */ - -static gfc_expr* -get_size_m1 (gfc_expr *e, int dimen) -{ - mpz_t size; - gfc_expr *res; - - if (gfc_array_dimen_size (e, dimen - 1, &size)) - { - res = gfc_get_constant_expr (BT_INTEGER, - gfc_index_integer_kind, &e->where); - mpz_sub_ui (res->value.integer, size, 1); - mpz_clear (size); - } - else - { - res = get_operand (INTRINSIC_MINUS, - get_array_inq_function (GFC_ISYM_SIZE, e, dimen), - gfc_get_int_expr (gfc_index_integer_kind, - &e->where, 1)); - gfc_simplify_expr (res, 0); - } - - return res; -} - -/* Function to return a scalarized expression. It is assumed that indices are - zero based to make generation of DO loops easier. A zero as index will - access the first element along a dimension. Single element references will - be skipped. A NULL as an expression will be replaced by a full reference. - This assumes that the index loops have gfc_index_integer_kind, and that all - references have been frozen. */ - -static gfc_expr* -scalarized_expr (gfc_expr *e_in, gfc_expr **index, int count_index) -{ - gfc_array_ref *ar; - int i; - int rank; - gfc_expr *e; - int i_index; - bool was_fullref; - - e = gfc_copy_expr(e_in); - - rank = e->rank; - - ar = gfc_find_array_ref (e); - - /* We scalarize count_index variables, reducing the rank by count_index. */ - - e->rank = rank - count_index; - - was_fullref = ar->type == AR_FULL; - - if (e->rank == 0) - ar->type = AR_ELEMENT; - else - ar->type = AR_SECTION; - - /* Loop over the indices. For each index, create the expression - index * stride + lbound(e, dim). */ - - i_index = 0; - for (i=0; i < ar->dimen; i++) - { - if (was_fullref || ar->dimen_type[i] == DIMEN_RANGE) - { - if (index[i_index] != NULL) - { - gfc_expr *lbound, *nindex; - gfc_expr *loopvar; - - loopvar = gfc_copy_expr (index[i_index]); - - if (ar->stride[i]) - { - gfc_expr *tmp; - - tmp = gfc_copy_expr(ar->stride[i]); - if (tmp->ts.kind != gfc_index_integer_kind) - { - gfc_typespec ts; - gfc_clear_ts (&ts); - ts.type = BT_INTEGER; - ts.kind = gfc_index_integer_kind; - gfc_convert_type (tmp, &ts, 2); - } - nindex = get_operand (INTRINSIC_TIMES, loopvar, tmp); - } - else - nindex = loopvar; - - /* Calculate the lower bound of the expression. */ - if (ar->start[i]) - { - lbound = gfc_copy_expr (ar->start[i]); - if (lbound->ts.kind != gfc_index_integer_kind) - { - gfc_typespec ts; - gfc_clear_ts (&ts); - ts.type = BT_INTEGER; - ts.kind = gfc_index_integer_kind; - gfc_convert_type (lbound, &ts, 2); - - } - } - else - { - gfc_expr *lbound_e; - gfc_ref *ref; - - lbound_e = gfc_copy_expr (e_in); - - for (ref = lbound_e->ref; ref; ref = ref->next) - if (ref->type == REF_ARRAY - && (ref->u.ar.type == AR_FULL - || ref->u.ar.type == AR_SECTION)) - break; - - if (ref->next) - { - gfc_free_ref_list (ref->next); - ref->next = NULL; - } - - if (!was_fullref) - { - /* Look at full individual sections, like a(:). The first index - is the lbound of a full ref. */ - int j; - gfc_array_ref *ar; - int to; - - ar = &ref->u.ar; - - /* For assumed size, we need to keep around the final - reference in order not to get an error on resolution - below, and we cannot use AR_FULL. */ - - if (ar->as->type == AS_ASSUMED_SIZE) - { - ar->type = AR_SECTION; - to = ar->dimen - 1; - } - else - { - to = ar->dimen; - ar->type = AR_FULL; - } - - for (j = 0; j < to; j++) - { - gfc_free_expr (ar->start[j]); - ar->start[j] = NULL; - gfc_free_expr (ar->end[j]); - ar->end[j] = NULL; - gfc_free_expr (ar->stride[j]); - ar->stride[j] = NULL; - } - - /* We have to get rid of the shape, if there is one. Do - so by freeing it and calling gfc_resolve to rebuild - it, if necessary. */ - - if (lbound_e->shape) - gfc_free_shape (&(lbound_e->shape), lbound_e->rank); - - lbound_e->rank = ar->dimen; - gfc_resolve_expr (lbound_e); - } - lbound = get_array_inq_function (GFC_ISYM_LBOUND, lbound_e, - i + 1); - gfc_free_expr (lbound_e); - } - - ar->dimen_type[i] = DIMEN_ELEMENT; - - gfc_free_expr (ar->start[i]); - ar->start[i] = get_operand (INTRINSIC_PLUS, nindex, lbound); - - gfc_free_expr (ar->end[i]); - ar->end[i] = NULL; - gfc_free_expr (ar->stride[i]); - ar->stride[i] = NULL; - gfc_simplify_expr (ar->start[i], 0); - } - else if (was_fullref) - { - gfc_internal_error ("Scalarization using DIMEN_RANGE unimplemented"); - } - i_index ++; - } - } - - /* Bounds checking will be done before the loops if -fcheck=bounds - is in effect. */ - e->no_bounds_check = 1; - return e; -} - -/* Helper function to check for a dimen vector as subscript. */ - -bool -gfc_has_dimen_vector_ref (gfc_expr *e) -{ - gfc_array_ref *ar; - int i; - - ar = gfc_find_array_ref (e); - gcc_assert (ar); - if (ar->type == AR_FULL) - return false; - - for (i=0; i<ar->dimen; i++) - if (ar->dimen_type[i] == DIMEN_VECTOR) - return true; - - return false; -} - -/* If handed an expression of the form - - TRANSPOSE(CONJG(A)) - - check if A can be handled by matmul and return if there is an uneven number - of CONJG calls. Return a pointer to the array when everything is OK, NULL - otherwise. The caller has to check for the correct rank. */ - -static gfc_expr* -check_conjg_transpose_variable (gfc_expr *e, bool *conjg, bool *transpose) -{ - *conjg = false; - *transpose = false; - - do - { - if (e->expr_type == EXPR_VARIABLE) - { - gcc_assert (e->rank == 1 || e->rank == 2); - return e; - } - else if (e->expr_type == EXPR_FUNCTION) - { - if (e->value.function.isym == NULL) - return NULL; - - if (e->value.function.isym->id == GFC_ISYM_CONJG) - *conjg = !*conjg; - else if (e->value.function.isym->id == GFC_ISYM_TRANSPOSE) - *transpose = !*transpose; - else return NULL; - } - else - return NULL; - - e = e->value.function.actual->expr; - } - while(1); - - return NULL; -} - -/* Macros for unified error messages. */ - -#define B_ERROR_1 _("Incorrect extent in argument B in MATMUL intrinsic in " \ - "dimension 1: is %ld, should be %ld") - -#define C_ERROR_1 _("Array bound mismatch for dimension 1 of array " \ - "(%ld/%ld)") - -#define C_ERROR_2 _("Array bound mismatch for dimension 2 of array " \ - "(%ld/%ld)") - - -/* Inline assignments of the form c = matmul(a,b). - Handle only the cases currently where b and c are rank-two arrays. - - This basically translates the code to - - BLOCK - integer i,j,k - c = 0 - do j=0, size(b,2)-1 - do k=0, size(a, 2)-1 - do i=0, size(a, 1)-1 - c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) = - c(i * stride(c,1) + lbound(c,1), j * stride(c,2) + lbound(c,2)) + - a(i * stride(a,1) + lbound(a,1), k * stride(a,2) + lbound(a,2)) * - b(k * stride(b,1) + lbound(b,1), j * stride(b,2) + lbound(b,2)) - end do - end do - end do - END BLOCK - -*/ - -static int -inline_matmul_assign (gfc_code **c, int *walk_subtrees, - void *data ATTRIBUTE_UNUSED) -{ - gfc_code *co = *c; - gfc_expr *expr1, *expr2; - gfc_expr *matrix_a, *matrix_b; - gfc_actual_arglist *a, *b; - gfc_code *do_1, *do_2, *do_3, *assign_zero, *assign_matmul; - gfc_expr *zero_e; - gfc_expr *u1, *u2, *u3; - gfc_expr *list[2]; - gfc_expr *ascalar, *bscalar, *cscalar; - gfc_expr *mult; - gfc_expr *var_1, *var_2, *var_3; - gfc_expr *zero; - gfc_namespace *ns; - gfc_intrinsic_op op_times, op_plus; - enum matrix_case m_case; - int i; - gfc_code *if_limit = NULL; - gfc_code **next_code_point; - bool conjg_a, conjg_b, transpose_a, transpose_b; - bool realloc_c; - - if (co->op != EXEC_ASSIGN) - return 0; - - if (in_where || in_assoc_list) - return 0; - - /* The BLOCKS generated for the temporary variables and FORALL don't - mix. */ - if (forall_level > 0) - return 0; - - /* For now don't do anything in OpenMP workshare, it confuses - its translation, which expects only the allowed statements in there. - We should figure out how to parallelize this eventually. */ - if (in_omp_workshare || in_omp_atomic) - return 0; - - expr1 = co->expr1; - expr2 = co->expr2; - if (expr2->expr_type != EXPR_FUNCTION - || expr2->value.function.isym == NULL - || expr2->value.function.isym->id != GFC_ISYM_MATMUL) - return 0; - - current_code = c; - inserted_block = NULL; - changed_statement = NULL; - - a = expr2->value.function.actual; - matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a); - if (matrix_a == NULL) - return 0; - - b = a->next; - matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b); - if (matrix_b == NULL) - return 0; - - if (gfc_has_dimen_vector_ref (expr1) || gfc_has_dimen_vector_ref (matrix_a) - || gfc_has_dimen_vector_ref (matrix_b)) - return 0; - - /* We do not handle data dependencies yet. */ - if (gfc_check_dependency (expr1, matrix_a, true) - || gfc_check_dependency (expr1, matrix_b, true)) - return 0; - - m_case = none; - if (matrix_a->rank == 2) - { - if (transpose_a) - { - if (matrix_b->rank == 2 && !transpose_b) - m_case = A2TB2; - } - else - { - if (matrix_b->rank == 1) - m_case = A2B1; - else /* matrix_b->rank == 2 */ - { - if (transpose_b) - m_case = A2B2T; - else - m_case = A2B2; - } - } - } - else /* matrix_a->rank == 1 */ - { - if (matrix_b->rank == 2) - { - if (!transpose_b) - m_case = A1B2; - } - } - - if (m_case == none) - return 0; - - /* We only handle assignment to numeric or logical variables. */ - switch(expr1->ts.type) - { - case BT_INTEGER: - case BT_LOGICAL: - case BT_REAL: - case BT_COMPLEX: - break; - - default: - return 0; - } - - ns = insert_block (); - - /* Assign the type of the zero expression for initializing the resulting - array, and the expression (+ and * for real, integer and complex; - .and. and .or for logical. */ - - switch(expr1->ts.type) - { - case BT_INTEGER: - zero_e = gfc_get_int_expr (expr1->ts.kind, &expr1->where, 0); - op_times = INTRINSIC_TIMES; - op_plus = INTRINSIC_PLUS; - break; - - case BT_LOGICAL: - op_times = INTRINSIC_AND; - op_plus = INTRINSIC_OR; - zero_e = gfc_get_logical_expr (expr1->ts.kind, &expr1->where, - 0); - break; - case BT_REAL: - zero_e = gfc_get_constant_expr (BT_REAL, expr1->ts.kind, - &expr1->where); - mpfr_set_si (zero_e->value.real, 0, GFC_RND_MODE); - op_times = INTRINSIC_TIMES; - op_plus = INTRINSIC_PLUS; - break; - - case BT_COMPLEX: - zero_e = gfc_get_constant_expr (BT_COMPLEX, expr1->ts.kind, - &expr1->where); - mpc_set_si_si (zero_e->value.complex, 0, 0, GFC_RND_MODE); - op_times = INTRINSIC_TIMES; - op_plus = INTRINSIC_PLUS; - - break; - - default: - gcc_unreachable(); - } - - current_code = &ns->code; - - /* Freeze the references, keeping track of how many temporary variables were - created. */ - n_vars = 0; - freeze_references (matrix_a); - freeze_references (matrix_b); - freeze_references (expr1); - - if (n_vars == 0) - next_code_point = current_code; - else - { - next_code_point = &ns->code; - for (i=0; i<n_vars; i++) - next_code_point = &(*next_code_point)->next; - } - - /* Take care of the inline flag. If the limit check evaluates to a - constant, dead code elimination will eliminate the unneeded branch. */ - - if (flag_inline_matmul_limit > 0 - && (matrix_a->rank == 1 || matrix_a->rank == 2) - && matrix_b->rank == 2) - { - if_limit = inline_limit_check (matrix_a, matrix_b, - flag_inline_matmul_limit, - matrix_a->rank); - - /* Insert the original statement into the else branch. */ - if_limit->block->block->next = co; - co->next = NULL; - - /* ... and the new ones go into the original one. */ - *next_code_point = if_limit; - next_code_point = &if_limit->block->next; - } - - zero_e->no_bounds_check = 1; - - assign_zero = XCNEW (gfc_code); - assign_zero->op = EXEC_ASSIGN; - assign_zero->loc = co->loc; - assign_zero->expr1 = gfc_copy_expr (expr1); - assign_zero->expr1->no_bounds_check = 1; - assign_zero->expr2 = zero_e; - - realloc_c = flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1); - - if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) - { - gfc_code *test; - gfc_expr *a2, *b1, *c1, *c2, *a1, *b2; - - switch (m_case) - { - case A2B1: - - b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1); - a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2); - test = runtime_error_ne (b1, a2, B_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - if (!realloc_c) - { - c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1); - a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1); - test = runtime_error_ne (c1, a1, C_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - } - break; - - case A1B2: - - b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1); - a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1); - test = runtime_error_ne (b1, a1, B_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - if (!realloc_c) - { - c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1); - b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2); - test = runtime_error_ne (c1, b2, C_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - } - break; - - case A2B2: - - b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1); - a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2); - test = runtime_error_ne (b1, a2, B_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - if (!realloc_c) - { - c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1); - a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1); - test = runtime_error_ne (c1, a1, C_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2); - b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2); - test = runtime_error_ne (c2, b2, C_ERROR_2); - *next_code_point = test; - next_code_point = &test->next; - } - break; - - case A2B2T: - - b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2); - a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2); - /* matrix_b is transposed, hence dimension 1 for the error message. */ - test = runtime_error_ne (b2, a2, B_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - if (!realloc_c) - { - c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1); - a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1); - test = runtime_error_ne (c1, a1, C_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2); - b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1); - test = runtime_error_ne (c2, b1, C_ERROR_2); - *next_code_point = test; - next_code_point = &test->next; - } - break; - - case A2TB2: - - b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1); - a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1); - test = runtime_error_ne (b1, a1, B_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - if (!realloc_c) - { - c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1); - a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2); - test = runtime_error_ne (c1, a2, C_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2); - b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2); - test = runtime_error_ne (c2, b2, C_ERROR_2); - *next_code_point = test; - next_code_point = &test->next; - } - break; - - default: - gcc_unreachable (); - } - } - - /* Handle the reallocation, if needed. */ - - if (realloc_c) - { - gfc_code *lhs_alloc; - - lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case); - - *next_code_point = lhs_alloc; - next_code_point = &lhs_alloc->next; - - } - - *next_code_point = assign_zero; - - zero = gfc_get_int_expr (gfc_index_integer_kind, &co->loc, 0); - - assign_matmul = XCNEW (gfc_code); - assign_matmul->op = EXEC_ASSIGN; - assign_matmul->loc = co->loc; - - /* Get the bounds for the loops, create them and create the scalarized - expressions. */ - - switch (m_case) - { - case A2B2: - - u1 = get_size_m1 (matrix_b, 2); - u2 = get_size_m1 (matrix_a, 2); - u3 = get_size_m1 (matrix_a, 1); - - do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns); - do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns); - do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns); - - do_1->block->next = do_2; - do_2->block->next = do_3; - do_3->block->next = assign_matmul; - - var_1 = do_1->ext.iterator->var; - var_2 = do_2->ext.iterator->var; - var_3 = do_3->ext.iterator->var; - - list[0] = var_3; - list[1] = var_1; - cscalar = scalarized_expr (co->expr1, list, 2); - - list[0] = var_3; - list[1] = var_2; - ascalar = scalarized_expr (matrix_a, list, 2); - - list[0] = var_2; - list[1] = var_1; - bscalar = scalarized_expr (matrix_b, list, 2); - - break; - - case A2B2T: - - u1 = get_size_m1 (matrix_b, 1); - u2 = get_size_m1 (matrix_a, 2); - u3 = get_size_m1 (matrix_a, 1); - - do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns); - do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns); - do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns); - - do_1->block->next = do_2; - do_2->block->next = do_3; - do_3->block->next = assign_matmul; - - var_1 = do_1->ext.iterator->var; - var_2 = do_2->ext.iterator->var; - var_3 = do_3->ext.iterator->var; - - list[0] = var_3; - list[1] = var_1; - cscalar = scalarized_expr (co->expr1, list, 2); - - list[0] = var_3; - list[1] = var_2; - ascalar = scalarized_expr (matrix_a, list, 2); - - list[0] = var_1; - list[1] = var_2; - bscalar = scalarized_expr (matrix_b, list, 2); - - break; - - case A2TB2: - - u1 = get_size_m1 (matrix_a, 2); - u2 = get_size_m1 (matrix_b, 2); - u3 = get_size_m1 (matrix_a, 1); - - do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns); - do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns); - do_3 = create_do_loop (gfc_copy_expr (zero), u3, NULL, &co->loc, ns); - - do_1->block->next = do_2; - do_2->block->next = do_3; - do_3->block->next = assign_matmul; - - var_1 = do_1->ext.iterator->var; - var_2 = do_2->ext.iterator->var; - var_3 = do_3->ext.iterator->var; - - list[0] = var_1; - list[1] = var_2; - cscalar = scalarized_expr (co->expr1, list, 2); - - list[0] = var_3; - list[1] = var_1; - ascalar = scalarized_expr (matrix_a, list, 2); - - list[0] = var_3; - list[1] = var_2; - bscalar = scalarized_expr (matrix_b, list, 2); - - break; - - case A2B1: - u1 = get_size_m1 (matrix_b, 1); - u2 = get_size_m1 (matrix_a, 1); - - do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns); - do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns); - - do_1->block->next = do_2; - do_2->block->next = assign_matmul; - - var_1 = do_1->ext.iterator->var; - var_2 = do_2->ext.iterator->var; - - list[0] = var_2; - cscalar = scalarized_expr (co->expr1, list, 1); - - list[0] = var_2; - list[1] = var_1; - ascalar = scalarized_expr (matrix_a, list, 2); - - list[0] = var_1; - bscalar = scalarized_expr (matrix_b, list, 1); - - break; - - case A1B2: - u1 = get_size_m1 (matrix_b, 2); - u2 = get_size_m1 (matrix_a, 1); - - do_1 = create_do_loop (gfc_copy_expr (zero), u1, NULL, &co->loc, ns); - do_2 = create_do_loop (gfc_copy_expr (zero), u2, NULL, &co->loc, ns); - - do_1->block->next = do_2; - do_2->block->next = assign_matmul; - - var_1 = do_1->ext.iterator->var; - var_2 = do_2->ext.iterator->var; - - list[0] = var_1; - cscalar = scalarized_expr (co->expr1, list, 1); - - list[0] = var_2; - ascalar = scalarized_expr (matrix_a, list, 1); - - list[0] = var_2; - list[1] = var_1; - bscalar = scalarized_expr (matrix_b, list, 2); - - break; - - default: - gcc_unreachable(); - } - - /* Build the conjg call around the variables. Set the typespec manually - because gfc_build_intrinsic_call sometimes gets this wrong. */ - if (conjg_a) - { - gfc_typespec ts; - ts = matrix_a->ts; - ascalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg", - matrix_a->where, 1, ascalar); - ascalar->ts = ts; - } - - if (conjg_b) - { - gfc_typespec ts; - ts = matrix_b->ts; - bscalar = gfc_build_intrinsic_call (ns, GFC_ISYM_CONJG, "conjg", - matrix_b->where, 1, bscalar); - bscalar->ts = ts; - } - /* First loop comes after the zero assignment. */ - assign_zero->next = do_1; - - /* Build the assignment expression in the loop. */ - assign_matmul->expr1 = gfc_copy_expr (cscalar); - - mult = get_operand (op_times, ascalar, bscalar); - assign_matmul->expr2 = get_operand (op_plus, cscalar, mult); - - /* If we don't want to keep the original statement around in - the else branch, we can free it. */ - - if (if_limit == NULL) - gfc_free_statements(co); - else - co->next = NULL; - - gfc_free_expr (zero); - *walk_subtrees = 0; - return 0; -} - -/* Change matmul function calls in the form of - - c = matmul(a,b) - - to the corresponding call to a BLAS routine, if applicable. */ - -static int -call_external_blas (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - gfc_code *co, *co_next; - gfc_expr *expr1, *expr2; - gfc_expr *matrix_a, *matrix_b; - gfc_code *if_limit = NULL; - gfc_actual_arglist *a, *b; - bool conjg_a, conjg_b, transpose_a, transpose_b; - gfc_code *call; - const char *blas_name; - const char *transa, *transb; - gfc_expr *c1, *c2, *b1; - gfc_actual_arglist *actual, *next; - bt type; - int kind; - enum matrix_case m_case; - bool realloc_c; - gfc_code **next_code_point; - - /* Many of the tests for inline matmul also apply here. */ - - co = *c; - - if (co->op != EXEC_ASSIGN) - return 0; - - if (in_where || in_assoc_list) - return 0; - - /* The BLOCKS generated for the temporary variables and FORALL don't - mix. */ - if (forall_level > 0) - return 0; - - /* For now don't do anything in OpenMP workshare, it confuses - its translation, which expects only the allowed statements in there. */ - - if (in_omp_workshare || in_omp_atomic) - return 0; - - expr1 = co->expr1; - expr2 = co->expr2; - if (expr2->expr_type != EXPR_FUNCTION - || expr2->value.function.isym == NULL - || expr2->value.function.isym->id != GFC_ISYM_MATMUL) - return 0; - - type = expr2->ts.type; - kind = expr2->ts.kind; - - /* Guard against recursion. */ - - if (expr2->external_blas) - return 0; - - if (type != expr1->ts.type || kind != expr1->ts.kind) - return 0; - - if (type == BT_REAL) - { - if (kind == 4) - blas_name = "sgemm"; - else if (kind == 8) - blas_name = "dgemm"; - else - return 0; - } - else if (type == BT_COMPLEX) - { - if (kind == 4) - blas_name = "cgemm"; - else if (kind == 8) - blas_name = "zgemm"; - else - return 0; - } - else - return 0; - - a = expr2->value.function.actual; - if (a->expr->rank != 2) - return 0; - - b = a->next; - if (b->expr->rank != 2) - return 0; - - matrix_a = check_conjg_transpose_variable (a->expr, &conjg_a, &transpose_a); - if (matrix_a == NULL) - return 0; - - if (transpose_a) - { - if (conjg_a) - transa = "C"; - else - transa = "T"; - } - else - transa = "N"; - - matrix_b = check_conjg_transpose_variable (b->expr, &conjg_b, &transpose_b); - if (matrix_b == NULL) - return 0; - - if (transpose_b) - { - if (conjg_b) - transb = "C"; - else - transb = "T"; - } - else - transb = "N"; - - if (transpose_a) - { - if (transpose_b) - m_case = A2TB2T; - else - m_case = A2TB2; - } - else - { - if (transpose_b) - m_case = A2B2T; - else - m_case = A2B2; - } - - current_code = c; - inserted_block = NULL; - changed_statement = NULL; - - expr2->external_blas = 1; - - /* We do not handle data dependencies yet. */ - if (gfc_check_dependency (expr1, matrix_a, true) - || gfc_check_dependency (expr1, matrix_b, true)) - return 0; - - /* Generate the if statement and hang it into the tree. */ - if_limit = inline_limit_check (matrix_a, matrix_b, flag_blas_matmul_limit, 2); - co_next = co->next; - (*current_code) = if_limit; - co->next = NULL; - if_limit->block->next = co; - - call = XCNEW (gfc_code); - call->loc = co->loc; - - /* Bounds checking - a bit simpler than for inlining since we only - have to take care of two-dimensional arrays here. */ - - realloc_c = flag_realloc_lhs && gfc_is_reallocatable_lhs (expr1); - next_code_point = &(if_limit->block->block->next); - - if (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) - { - gfc_code *test; - // gfc_expr *a2, *b1, *c1, *c2, *a1, *b2; - gfc_expr *c1, *a1, *c2, *b2, *a2; - switch (m_case) - { - case A2B2: - b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1); - a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2); - test = runtime_error_ne (b1, a2, B_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - if (!realloc_c) - { - c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1); - a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1); - test = runtime_error_ne (c1, a1, C_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2); - b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2); - test = runtime_error_ne (c2, b2, C_ERROR_2); - *next_code_point = test; - next_code_point = &test->next; - } - break; - - case A2B2T: - - b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2); - a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2); - /* matrix_b is transposed, hence dimension 1 for the error message. */ - test = runtime_error_ne (b2, a2, B_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - if (!realloc_c) - { - c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1); - a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1); - test = runtime_error_ne (c1, a1, C_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2); - b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1); - test = runtime_error_ne (c2, b1, C_ERROR_2); - *next_code_point = test; - next_code_point = &test->next; - } - break; - - case A2TB2: - - b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1); - a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1); - test = runtime_error_ne (b1, a1, B_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - if (!realloc_c) - { - c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1); - a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2); - test = runtime_error_ne (c1, a2, C_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2); - b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2); - test = runtime_error_ne (c2, b2, C_ERROR_2); - *next_code_point = test; - next_code_point = &test->next; - } - break; - - case A2TB2T: - b2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 2); - a1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 1); - test = runtime_error_ne (b2, a1, B_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - if (!realloc_c) - { - c1 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 1); - a2 = get_array_inq_function (GFC_ISYM_SIZE, matrix_a, 2); - test = runtime_error_ne (c1, a2, C_ERROR_1); - *next_code_point = test; - next_code_point = &test->next; - - c2 = get_array_inq_function (GFC_ISYM_SIZE, expr1, 2); - b1 = get_array_inq_function (GFC_ISYM_SIZE, matrix_b, 1); - test = runtime_error_ne (c2, b1, C_ERROR_2); - *next_code_point = test; - next_code_point = &test->next; - } - break; - - default: - gcc_unreachable (); - } - } - - /* Handle the reallocation, if needed. */ - - if (realloc_c) - { - gfc_code *lhs_alloc; - - lhs_alloc = matmul_lhs_realloc (expr1, matrix_a, matrix_b, m_case); - *next_code_point = lhs_alloc; - next_code_point = &lhs_alloc->next; - } - - *next_code_point = call; - if_limit->next = co_next; - - /* Set up the BLAS call. */ - - call->op = EXEC_CALL; - - gfc_get_sym_tree (blas_name, current_ns, &(call->symtree), true); - call->symtree->n.sym->attr.subroutine = 1; - call->symtree->n.sym->attr.procedure = 1; - call->symtree->n.sym->attr.flavor = FL_PROCEDURE; - call->resolved_sym = call->symtree->n.sym; - gfc_commit_symbol (call->resolved_sym); - - /* Argument TRANSA. */ - next = gfc_get_actual_arglist (); - next->expr = gfc_get_character_expr (gfc_default_character_kind, &co->loc, - transa, 1); - - call->ext.actual = next; - - /* Argument TRANSB. */ - actual = next; - next = gfc_get_actual_arglist (); - next->expr = gfc_get_character_expr (gfc_default_character_kind, &co->loc, - transb, 1); - actual->next = next; - - c1 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (a->expr), 1, - gfc_integer_4_kind); - c2 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (b->expr), 2, - gfc_integer_4_kind); - - b1 = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (b->expr), 1, - gfc_integer_4_kind); - - /* Argument M. */ - actual = next; - next = gfc_get_actual_arglist (); - next->expr = c1; - actual->next = next; - - /* Argument N. */ - actual = next; - next = gfc_get_actual_arglist (); - next->expr = c2; - actual->next = next; - - /* Argument K. */ - actual = next; - next = gfc_get_actual_arglist (); - next->expr = b1; - actual->next = next; - - /* Argument ALPHA - set to one. */ - actual = next; - next = gfc_get_actual_arglist (); - next->expr = gfc_get_constant_expr (type, kind, &co->loc); - if (type == BT_REAL) - mpfr_set_ui (next->expr->value.real, 1, GFC_RND_MODE); - else - mpc_set_ui (next->expr->value.complex, 1, GFC_MPC_RND_MODE); - actual->next = next; - - /* Argument A. */ - actual = next; - next = gfc_get_actual_arglist (); - next->expr = gfc_copy_expr (matrix_a); - actual->next = next; - - /* Argument LDA. */ - actual = next; - next = gfc_get_actual_arglist (); - next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (matrix_a), - 1, gfc_integer_4_kind); - actual->next = next; - - /* Argument B. */ - actual = next; - next = gfc_get_actual_arglist (); - next->expr = gfc_copy_expr (matrix_b); - actual->next = next; - - /* Argument LDB. */ - actual = next; - next = gfc_get_actual_arglist (); - next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (matrix_b), - 1, gfc_integer_4_kind); - actual->next = next; - - /* Argument BETA - set to zero. */ - actual = next; - next = gfc_get_actual_arglist (); - next->expr = gfc_get_constant_expr (type, kind, &co->loc); - if (type == BT_REAL) - mpfr_set_ui (next->expr->value.real, 0, GFC_RND_MODE); - else - mpc_set_ui (next->expr->value.complex, 0, GFC_MPC_RND_MODE); - actual->next = next; - - /* Argument C. */ - - actual = next; - next = gfc_get_actual_arglist (); - next->expr = gfc_copy_expr (expr1); - actual->next = next; - - /* Argument LDC. */ - actual = next; - next = gfc_get_actual_arglist (); - next->expr = get_array_inq_function (GFC_ISYM_SIZE, gfc_copy_expr (expr1), - 1, gfc_integer_4_kind); - actual->next = next; - - return 0; -} - - -/* Code for index interchange for loops which are grouped together in DO - CONCURRENT or FORALL statements. This is currently only applied if the - iterations are grouped together in a single statement. - - For this transformation, it is assumed that memory access in strides is - expensive, and that loops which access later indices (which access memory - in bigger strides) should be moved to the first loops. - - For this, a loop over all the statements is executed, counting the times - that the loop iteration values are accessed in each index. The loop - indices are then sorted to minimize access to later indices from inner - loops. */ - -/* Type for holding index information. */ - -typedef struct { - gfc_symbol *sym; - gfc_forall_iterator *fa; - int num; - int n[GFC_MAX_DIMENSIONS]; -} ind_type; - -/* Callback function to determine if an expression is the - corresponding variable. */ - -static int -has_var (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, void *data) -{ - gfc_expr *expr = *e; - gfc_symbol *sym; - - if (expr->expr_type != EXPR_VARIABLE) - return 0; - - sym = (gfc_symbol *) data; - return sym == expr->symtree->n.sym; -} - -/* Callback function to calculate the cost of a certain index. */ - -static int -index_cost (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data) -{ - ind_type *ind; - gfc_expr *expr; - gfc_array_ref *ar; - gfc_ref *ref; - int i,j; - - expr = *e; - if (expr->expr_type != EXPR_VARIABLE) - return 0; - - ar = NULL; - for (ref = expr->ref; ref; ref = ref->next) - { - if (ref->type == REF_ARRAY) - { - ar = &ref->u.ar; - break; - } - } - if (ar == NULL || ar->type != AR_ELEMENT) - return 0; - - ind = (ind_type *) data; - for (i = 0; i < ar->dimen; i++) - { - for (j=0; ind[j].sym != NULL; j++) - { - if (gfc_expr_walker (&ar->start[i], has_var, (void *) (ind[j].sym))) - ind[j].n[i]++; - } - } - return 0; -} - -/* Callback function for qsort, to sort the loop indices. */ - -static int -loop_comp (const void *e1, const void *e2) -{ - const ind_type *i1 = (const ind_type *) e1; - const ind_type *i2 = (const ind_type *) e2; - int i; - - for (i=GFC_MAX_DIMENSIONS-1; i >= 0; i--) - { - if (i1->n[i] != i2->n[i]) - return i1->n[i] - i2->n[i]; - } - /* All other things being equal, let's not change the ordering. */ - return i2->num - i1->num; -} - -/* Main function to do the index interchange. */ - -static int -index_interchange (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - gfc_code *co; - co = *c; - int n_iter; - gfc_forall_iterator *fa; - ind_type *ind; - int i, j; - - if (co->op != EXEC_FORALL && co->op != EXEC_DO_CONCURRENT) - return 0; - - n_iter = 0; - for (fa = co->ext.forall_iterator; fa; fa = fa->next) - n_iter ++; - - /* Nothing to reorder. */ - if (n_iter < 2) - return 0; - - ind = XALLOCAVEC (ind_type, n_iter + 1); - - i = 0; - for (fa = co->ext.forall_iterator; fa; fa = fa->next) - { - ind[i].sym = fa->var->symtree->n.sym; - ind[i].fa = fa; - for (j=0; j<GFC_MAX_DIMENSIONS; j++) - ind[i].n[j] = 0; - ind[i].num = i; - i++; - } - ind[n_iter].sym = NULL; - ind[n_iter].fa = NULL; - - gfc_code_walker (c, gfc_dummy_code_callback, index_cost, (void *) ind); - qsort ((void *) ind, n_iter, sizeof (ind_type), loop_comp); - - /* Do the actual index interchange. */ - co->ext.forall_iterator = fa = ind[0].fa; - for (i=1; i<n_iter; i++) - { - fa->next = ind[i].fa; - fa = fa->next; - } - fa->next = NULL; - - if (flag_warn_frontend_loop_interchange) - { - for (i=1; i<n_iter; i++) - { - if (ind[i-1].num > ind[i].num) - { - gfc_warning (OPT_Wfrontend_loop_interchange, - "Interchanging loops at %L", &co->loc); - break; - } - } - } - - return 0; -} - -#define WALK_SUBEXPR(NODE) \ - do \ - { \ - result = gfc_expr_walker (&(NODE), exprfn, data); \ - if (result) \ - return result; \ - } \ - while (0) -#define WALK_SUBEXPR_TAIL(NODE) e = &(NODE); continue - -/* Walk expression *E, calling EXPRFN on each expression in it. */ - -int -gfc_expr_walker (gfc_expr **e, walk_expr_fn_t exprfn, void *data) -{ - while (*e) - { - int walk_subtrees = 1; - gfc_actual_arglist *a; - gfc_ref *r; - gfc_constructor *c; - - int result = exprfn (e, &walk_subtrees, data); - if (result) - return result; - if (walk_subtrees) - switch ((*e)->expr_type) - { - case EXPR_OP: - WALK_SUBEXPR ((*e)->value.op.op1); - WALK_SUBEXPR_TAIL ((*e)->value.op.op2); - /* No fallthru because of the tail recursion above. */ - case EXPR_FUNCTION: - for (a = (*e)->value.function.actual; a; a = a->next) - WALK_SUBEXPR (a->expr); - break; - case EXPR_COMPCALL: - case EXPR_PPC: - WALK_SUBEXPR ((*e)->value.compcall.base_object); - for (a = (*e)->value.compcall.actual; a; a = a->next) - WALK_SUBEXPR (a->expr); - break; - - case EXPR_STRUCTURE: - case EXPR_ARRAY: - for (c = gfc_constructor_first ((*e)->value.constructor); c; - c = gfc_constructor_next (c)) - { - if (c->iterator == NULL) - WALK_SUBEXPR (c->expr); - else - { - iterator_level ++; - WALK_SUBEXPR (c->expr); - iterator_level --; - WALK_SUBEXPR (c->iterator->var); - WALK_SUBEXPR (c->iterator->start); - WALK_SUBEXPR (c->iterator->end); - WALK_SUBEXPR (c->iterator->step); - } - } - - if ((*e)->expr_type != EXPR_ARRAY) - break; - - /* Fall through to the variable case in order to walk the - reference. */ - gcc_fallthrough (); - - case EXPR_SUBSTRING: - case EXPR_VARIABLE: - for (r = (*e)->ref; r; r = r->next) - { - gfc_array_ref *ar; - int i; - - switch (r->type) - { - case REF_ARRAY: - ar = &r->u.ar; - if (ar->type == AR_SECTION || ar->type == AR_ELEMENT) - { - for (i=0; i< ar->dimen; i++) - { - WALK_SUBEXPR (ar->start[i]); - WALK_SUBEXPR (ar->end[i]); - WALK_SUBEXPR (ar->stride[i]); - } - } - - break; - - case REF_SUBSTRING: - WALK_SUBEXPR (r->u.ss.start); - WALK_SUBEXPR (r->u.ss.end); - break; - - case REF_COMPONENT: - case REF_INQUIRY: - break; - } - } - - default: - break; - } - return 0; - } - return 0; -} - -#define WALK_SUBCODE(NODE) \ - do \ - { \ - result = gfc_code_walker (&(NODE), codefn, exprfn, data); \ - if (result) \ - return result; \ - } \ - while (0) - -/* Walk code *C, calling CODEFN on each gfc_code node in it and calling EXPRFN - on each expression in it. If any of the hooks returns non-zero, that - value is immediately returned. If the hook sets *WALK_SUBTREES to 0, - no subcodes or subexpressions are traversed. */ - -int -gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn, - void *data) -{ - for (; *c; c = &(*c)->next) - { - int walk_subtrees = 1; - int result = codefn (c, &walk_subtrees, data); - if (result) - return result; - - if (walk_subtrees) - { - gfc_code *b; - gfc_actual_arglist *a; - gfc_code *co; - gfc_association_list *alist; - bool saved_in_omp_workshare; - bool saved_in_omp_atomic; - bool saved_in_where; - - /* There might be statement insertions before the current code, - which must not affect the expression walker. */ - - co = *c; - saved_in_omp_workshare = in_omp_workshare; - saved_in_omp_atomic = in_omp_atomic; - saved_in_where = in_where; - - switch (co->op) - { - - case EXEC_BLOCK: - WALK_SUBCODE (co->ext.block.ns->code); - if (co->ext.block.assoc) - { - bool saved_in_assoc_list = in_assoc_list; - - in_assoc_list = true; - for (alist = co->ext.block.assoc; alist; alist = alist->next) - WALK_SUBEXPR (alist->target); - - in_assoc_list = saved_in_assoc_list; - } - - break; - - case EXEC_DO: - doloop_level ++; - WALK_SUBEXPR (co->ext.iterator->var); - WALK_SUBEXPR (co->ext.iterator->start); - WALK_SUBEXPR (co->ext.iterator->end); - WALK_SUBEXPR (co->ext.iterator->step); - break; - - case EXEC_IF: - if_level ++; - break; - - case EXEC_WHERE: - in_where = true; - break; - - case EXEC_CALL: - case EXEC_ASSIGN_CALL: - for (a = co->ext.actual; a; a = a->next) - WALK_SUBEXPR (a->expr); - break; - - case EXEC_CALL_PPC: - WALK_SUBEXPR (co->expr1); - for (a = co->ext.actual; a; a = a->next) - WALK_SUBEXPR (a->expr); - break; - - case EXEC_SELECT: - WALK_SUBEXPR (co->expr1); - select_level ++; - for (b = co->block; b; b = b->block) - { - gfc_case *cp; - for (cp = b->ext.block.case_list; cp; cp = cp->next) - { - WALK_SUBEXPR (cp->low); - WALK_SUBEXPR (cp->high); - } - WALK_SUBCODE (b->next); - } - continue; - - case EXEC_ALLOCATE: - case EXEC_DEALLOCATE: - { - gfc_alloc *a; - for (a = co->ext.alloc.list; a; a = a->next) - WALK_SUBEXPR (a->expr); - break; - } - - case EXEC_FORALL: - case EXEC_DO_CONCURRENT: - { - gfc_forall_iterator *fa; - for (fa = co->ext.forall_iterator; fa; fa = fa->next) - { - WALK_SUBEXPR (fa->var); - WALK_SUBEXPR (fa->start); - WALK_SUBEXPR (fa->end); - WALK_SUBEXPR (fa->stride); - } - if (co->op == EXEC_FORALL) - forall_level ++; - break; - } - - case EXEC_OPEN: - WALK_SUBEXPR (co->ext.open->unit); - WALK_SUBEXPR (co->ext.open->file); - WALK_SUBEXPR (co->ext.open->status); - WALK_SUBEXPR (co->ext.open->access); - WALK_SUBEXPR (co->ext.open->form); - WALK_SUBEXPR (co->ext.open->recl); - WALK_SUBEXPR (co->ext.open->blank); - WALK_SUBEXPR (co->ext.open->position); - WALK_SUBEXPR (co->ext.open->action); - WALK_SUBEXPR (co->ext.open->delim); - WALK_SUBEXPR (co->ext.open->pad); - WALK_SUBEXPR (co->ext.open->iostat); - WALK_SUBEXPR (co->ext.open->iomsg); - WALK_SUBEXPR (co->ext.open->convert); - WALK_SUBEXPR (co->ext.open->decimal); - WALK_SUBEXPR (co->ext.open->encoding); - WALK_SUBEXPR (co->ext.open->round); - WALK_SUBEXPR (co->ext.open->sign); - WALK_SUBEXPR (co->ext.open->asynchronous); - WALK_SUBEXPR (co->ext.open->id); - WALK_SUBEXPR (co->ext.open->newunit); - WALK_SUBEXPR (co->ext.open->share); - WALK_SUBEXPR (co->ext.open->cc); - break; - - case EXEC_CLOSE: - WALK_SUBEXPR (co->ext.close->unit); - WALK_SUBEXPR (co->ext.close->status); - WALK_SUBEXPR (co->ext.close->iostat); - WALK_SUBEXPR (co->ext.close->iomsg); - break; - - case EXEC_BACKSPACE: - case EXEC_ENDFILE: - case EXEC_REWIND: - case EXEC_FLUSH: - WALK_SUBEXPR (co->ext.filepos->unit); - WALK_SUBEXPR (co->ext.filepos->iostat); - WALK_SUBEXPR (co->ext.filepos->iomsg); - break; - - case EXEC_INQUIRE: - WALK_SUBEXPR (co->ext.inquire->unit); - WALK_SUBEXPR (co->ext.inquire->file); - WALK_SUBEXPR (co->ext.inquire->iomsg); - WALK_SUBEXPR (co->ext.inquire->iostat); - WALK_SUBEXPR (co->ext.inquire->exist); - WALK_SUBEXPR (co->ext.inquire->opened); - WALK_SUBEXPR (co->ext.inquire->number); - WALK_SUBEXPR (co->ext.inquire->named); - WALK_SUBEXPR (co->ext.inquire->name); - WALK_SUBEXPR (co->ext.inquire->access); - WALK_SUBEXPR (co->ext.inquire->sequential); - WALK_SUBEXPR (co->ext.inquire->direct); - WALK_SUBEXPR (co->ext.inquire->form); - WALK_SUBEXPR (co->ext.inquire->formatted); - WALK_SUBEXPR (co->ext.inquire->unformatted); - WALK_SUBEXPR (co->ext.inquire->recl); - WALK_SUBEXPR (co->ext.inquire->nextrec); - WALK_SUBEXPR (co->ext.inquire->blank); - WALK_SUBEXPR (co->ext.inquire->position); - WALK_SUBEXPR (co->ext.inquire->action); - WALK_SUBEXPR (co->ext.inquire->read); - WALK_SUBEXPR (co->ext.inquire->write); - WALK_SUBEXPR (co->ext.inquire->readwrite); - WALK_SUBEXPR (co->ext.inquire->delim); - WALK_SUBEXPR (co->ext.inquire->encoding); - WALK_SUBEXPR (co->ext.inquire->pad); - WALK_SUBEXPR (co->ext.inquire->iolength); - WALK_SUBEXPR (co->ext.inquire->convert); - WALK_SUBEXPR (co->ext.inquire->strm_pos); - WALK_SUBEXPR (co->ext.inquire->asynchronous); - WALK_SUBEXPR (co->ext.inquire->decimal); - WALK_SUBEXPR (co->ext.inquire->pending); - WALK_SUBEXPR (co->ext.inquire->id); - WALK_SUBEXPR (co->ext.inquire->sign); - WALK_SUBEXPR (co->ext.inquire->size); - WALK_SUBEXPR (co->ext.inquire->round); - break; - - case EXEC_WAIT: - WALK_SUBEXPR (co->ext.wait->unit); - WALK_SUBEXPR (co->ext.wait->iostat); - WALK_SUBEXPR (co->ext.wait->iomsg); - WALK_SUBEXPR (co->ext.wait->id); - break; - - case EXEC_READ: - case EXEC_WRITE: - WALK_SUBEXPR (co->ext.dt->io_unit); - WALK_SUBEXPR (co->ext.dt->format_expr); - WALK_SUBEXPR (co->ext.dt->rec); - WALK_SUBEXPR (co->ext.dt->advance); - WALK_SUBEXPR (co->ext.dt->iostat); - WALK_SUBEXPR (co->ext.dt->size); - WALK_SUBEXPR (co->ext.dt->iomsg); - WALK_SUBEXPR (co->ext.dt->id); - WALK_SUBEXPR (co->ext.dt->pos); - WALK_SUBEXPR (co->ext.dt->asynchronous); - WALK_SUBEXPR (co->ext.dt->blank); - WALK_SUBEXPR (co->ext.dt->decimal); - WALK_SUBEXPR (co->ext.dt->delim); - WALK_SUBEXPR (co->ext.dt->pad); - WALK_SUBEXPR (co->ext.dt->round); - WALK_SUBEXPR (co->ext.dt->sign); - WALK_SUBEXPR (co->ext.dt->extra_comma); - break; - - case EXEC_OACC_ATOMIC: - case EXEC_OMP_ATOMIC: - in_omp_atomic = true; - break; - - case EXEC_OMP_PARALLEL: - case EXEC_OMP_PARALLEL_DO: - case EXEC_OMP_PARALLEL_DO_SIMD: - case EXEC_OMP_PARALLEL_LOOP: - case EXEC_OMP_PARALLEL_MASKED: - case EXEC_OMP_PARALLEL_MASKED_TASKLOOP: - case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD: - case EXEC_OMP_PARALLEL_MASTER: - case EXEC_OMP_PARALLEL_MASTER_TASKLOOP: - case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD: - case EXEC_OMP_PARALLEL_SECTIONS: - - in_omp_workshare = false; - - /* This goto serves as a shortcut to avoid code - duplication or a larger if or switch statement. */ - goto check_omp_clauses; - - case EXEC_OMP_WORKSHARE: - case EXEC_OMP_PARALLEL_WORKSHARE: - - in_omp_workshare = true; - - /* Fall through */ - - case EXEC_OMP_CRITICAL: - case EXEC_OMP_DISTRIBUTE: - case EXEC_OMP_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_DISTRIBUTE_SIMD: - case EXEC_OMP_DO: - case EXEC_OMP_DO_SIMD: - case EXEC_OMP_LOOP: - case EXEC_OMP_ORDERED: - case EXEC_OMP_SECTIONS: - case EXEC_OMP_SINGLE: - case EXEC_OMP_END_SINGLE: - case EXEC_OMP_SIMD: - case EXEC_OMP_TASKLOOP: - case EXEC_OMP_TASKLOOP_SIMD: - case EXEC_OMP_TARGET: - case EXEC_OMP_TARGET_DATA: - case EXEC_OMP_TARGET_ENTER_DATA: - case EXEC_OMP_TARGET_EXIT_DATA: - case EXEC_OMP_TARGET_PARALLEL: - case EXEC_OMP_TARGET_PARALLEL_DO: - case EXEC_OMP_TARGET_PARALLEL_DO_SIMD: - case EXEC_OMP_TARGET_PARALLEL_LOOP: - case EXEC_OMP_TARGET_SIMD: - case EXEC_OMP_TARGET_TEAMS: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD: - case EXEC_OMP_TARGET_TEAMS_LOOP: - case EXEC_OMP_TARGET_UPDATE: - case EXEC_OMP_TASK: - case EXEC_OMP_TEAMS: - case EXEC_OMP_TEAMS_DISTRIBUTE: - case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: - case EXEC_OMP_TEAMS_LOOP: - - /* Come to this label only from the - EXEC_OMP_PARALLEL_* cases above. */ - - check_omp_clauses: - - if (co->ext.omp_clauses) - { - gfc_omp_namelist *n; - static int list_types[] - = { OMP_LIST_ALIGNED, OMP_LIST_LINEAR, OMP_LIST_DEPEND, - OMP_LIST_MAP, OMP_LIST_TO, OMP_LIST_FROM }; - size_t idx; - WALK_SUBEXPR (co->ext.omp_clauses->if_expr); - WALK_SUBEXPR (co->ext.omp_clauses->final_expr); - WALK_SUBEXPR (co->ext.omp_clauses->num_threads); - WALK_SUBEXPR (co->ext.omp_clauses->chunk_size); - WALK_SUBEXPR (co->ext.omp_clauses->safelen_expr); - WALK_SUBEXPR (co->ext.omp_clauses->simdlen_expr); - WALK_SUBEXPR (co->ext.omp_clauses->num_teams_lower); - WALK_SUBEXPR (co->ext.omp_clauses->num_teams_upper); - WALK_SUBEXPR (co->ext.omp_clauses->device); - WALK_SUBEXPR (co->ext.omp_clauses->thread_limit); - WALK_SUBEXPR (co->ext.omp_clauses->dist_chunk_size); - WALK_SUBEXPR (co->ext.omp_clauses->grainsize); - WALK_SUBEXPR (co->ext.omp_clauses->hint); - WALK_SUBEXPR (co->ext.omp_clauses->num_tasks); - WALK_SUBEXPR (co->ext.omp_clauses->priority); - WALK_SUBEXPR (co->ext.omp_clauses->detach); - for (idx = 0; idx < OMP_IF_LAST; idx++) - WALK_SUBEXPR (co->ext.omp_clauses->if_exprs[idx]); - for (idx = 0; - idx < sizeof (list_types) / sizeof (list_types[0]); - idx++) - for (n = co->ext.omp_clauses->lists[list_types[idx]]; - n; n = n->next) - WALK_SUBEXPR (n->expr); - } - break; - default: - break; - } - - WALK_SUBEXPR (co->expr1); - WALK_SUBEXPR (co->expr2); - WALK_SUBEXPR (co->expr3); - WALK_SUBEXPR (co->expr4); - for (b = co->block; b; b = b->block) - { - WALK_SUBEXPR (b->expr1); - WALK_SUBEXPR (b->expr2); - WALK_SUBCODE (b->next); - } - - if (co->op == EXEC_FORALL) - forall_level --; - - if (co->op == EXEC_DO) - doloop_level --; - - if (co->op == EXEC_IF) - if_level --; - - if (co->op == EXEC_SELECT) - select_level --; - - in_omp_workshare = saved_in_omp_workshare; - in_omp_atomic = saved_in_omp_atomic; - in_where = saved_in_where; - } - } - return 0; -} - -/* As a post-resolution step, check that all global symbols which are - not declared in the source file match in their call signatures. - We do this by looping over the code (and expressions). The first call - we happen to find is assumed to be canonical. */ - - -/* Common tests for argument checking for both functions and subroutines. */ - -static int -check_externals_procedure (gfc_symbol *sym, locus *loc, - gfc_actual_arglist *actual) -{ - gfc_gsymbol *gsym; - gfc_symbol *def_sym = NULL; - - if (sym == NULL || sym->attr.is_bind_c) - return 0; - - if (sym->attr.proc != PROC_EXTERNAL && sym->attr.proc != PROC_UNKNOWN) - return 0; - - if (sym->attr.if_source == IFSRC_IFBODY || sym->attr.if_source == IFSRC_DECL) - return 0; - - gsym = gfc_find_gsymbol (gfc_gsym_root, sym->name); - if (gsym == NULL) - return 0; - - if (gsym->ns) - gfc_find_symbol (sym->name, gsym->ns, 0, &def_sym); - - if (def_sym) - { - gfc_compare_actual_formal (&actual, def_sym->formal, 0, 0, 0, loc); - return 0; - } - - /* First time we have seen this procedure called. Let's create an - "interface" from the call and put it into a new namespace. */ - gfc_namespace *save_ns; - gfc_symbol *new_sym; - - gsym->where = *loc; - save_ns = gfc_current_ns; - gsym->ns = gfc_get_namespace (gfc_current_ns, 0); - gsym->ns->proc_name = sym; - - gfc_get_symbol (sym->name, gsym->ns, &new_sym); - gcc_assert (new_sym); - new_sym->attr = sym->attr; - new_sym->attr.if_source = IFSRC_DECL; - gfc_current_ns = gsym->ns; - - gfc_get_formal_from_actual_arglist (new_sym, actual); - new_sym->declared_at = *loc; - gfc_current_ns = save_ns; - - return 0; - -} - -/* Callback for calls of external routines. */ - -static int -check_externals_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - gfc_code *co = *c; - gfc_symbol *sym; - locus *loc; - gfc_actual_arglist *actual; - - if (co->op != EXEC_CALL) - return 0; - - sym = co->resolved_sym; - loc = &co->loc; - actual = co->ext.actual; - - return check_externals_procedure (sym, loc, actual); - -} - -/* Callback for external functions. */ - -static int -check_externals_expr (gfc_expr **ep, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) -{ - gfc_expr *e = *ep; - gfc_symbol *sym; - locus *loc; - gfc_actual_arglist *actual; - - if (e->expr_type != EXPR_FUNCTION) - return 0; - - sym = e->value.function.esym; - if (sym == NULL) - return 0; - - loc = &e->where; - actual = e->value.function.actual; - - return check_externals_procedure (sym, loc, actual); -} - -/* Function to check if any interface clashes with a global - identifier, to be invoked via gfc_traverse_ns. */ - -static void -check_against_globals (gfc_symbol *sym) -{ - gfc_gsymbol *gsym; - gfc_symbol *def_sym = NULL; - const char *sym_name; - char buf [200]; - - if (sym->attr.if_source != IFSRC_IFBODY || sym->attr.flavor != FL_PROCEDURE - || sym->attr.generic || sym->error) - return; - - if (sym->binding_label) - sym_name = sym->binding_label; - else - sym_name = sym->name; - - gsym = gfc_find_gsymbol (gfc_gsym_root, sym_name); - if (gsym && gsym->ns) - gfc_find_symbol (sym->name, gsym->ns, 0, &def_sym); - - if (!def_sym || def_sym->error || def_sym->attr.generic) - return; - - buf[0] = 0; - gfc_compare_interfaces (sym, def_sym, sym->name, 0, 1, buf, sizeof(buf), - NULL, NULL, NULL); - if (buf[0] != 0) - { - gfc_warning (0, "%s between %L and %L", buf, &def_sym->declared_at, - &sym->declared_at); - sym->error = 1; - def_sym->error = 1; - } - -} - -/* Do the code-walkling part for gfc_check_externals. */ - -static void -gfc_check_externals0 (gfc_namespace *ns) -{ - gfc_code_walker (&ns->code, check_externals_code, check_externals_expr, NULL); - - for (ns = ns->contained; ns; ns = ns->sibling) - { - if (ns->code == NULL || ns->code->op != EXEC_BLOCK) - gfc_check_externals0 (ns); - } - -} - -/* Called routine. */ - -void -gfc_check_externals (gfc_namespace *ns) -{ - gfc_clear_error (); - - /* Turn errors into warnings if the user indicated this. */ - - if (!pedantic && flag_allow_argument_mismatch) - gfc_errors_to_warnings (true); - - gfc_check_externals0 (ns); - gfc_traverse_ns (ns, check_against_globals); - - gfc_errors_to_warnings (false); -} - -/* Callback function. If there is a call to a subroutine which is - neither pure nor implicit_pure, unset the implicit_pure flag for - the caller and return -1. */ - -static int -implicit_pure_call (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED, - void *sym_data) -{ - gfc_code *co = *c; - gfc_symbol *caller_sym; - symbol_attribute *a; - - if (co->op != EXEC_CALL || co->resolved_sym == NULL) - return 0; - - a = &co->resolved_sym->attr; - if (a->intrinsic || a->pure || a->implicit_pure) - return 0; - - caller_sym = (gfc_symbol *) sym_data; - gfc_unset_implicit_pure (caller_sym); - return 1; -} - -/* Callback function. If there is a call to a function which is - neither pure nor implicit_pure, unset the implicit_pure flag for - the caller and return 1. */ - -static int -implicit_pure_expr (gfc_expr **e, int *walk ATTRIBUTE_UNUSED, void *sym_data) -{ - gfc_expr *expr = *e; - gfc_symbol *caller_sym; - gfc_symbol *sym; - symbol_attribute *a; - - if (expr->expr_type != EXPR_FUNCTION || expr->value.function.isym) - return 0; - - sym = expr->symtree->n.sym; - a = &sym->attr; - if (a->pure || a->implicit_pure) - return 0; - - caller_sym = (gfc_symbol *) sym_data; - gfc_unset_implicit_pure (caller_sym); - return 1; -} - -/* Go through all procedures in the namespace and unset the - implicit_pure attribute for any procedure that calls something not - pure or implicit pure. */ - -bool -gfc_fix_implicit_pure (gfc_namespace *ns) -{ - bool changed = false; - gfc_symbol *proc = ns->proc_name; - - if (proc && proc->attr.flavor == FL_PROCEDURE && proc->attr.implicit_pure - && ns->code - && gfc_code_walker (&ns->code, implicit_pure_call, implicit_pure_expr, - (void *) ns->proc_name)) - changed = true; - - for (ns = ns->contained; ns; ns = ns->sibling) - { - if (gfc_fix_implicit_pure (ns)) - changed = true; - } - - return changed; -} |